From: Gabriele Monaco <gmonaco@redhat.com>
To: linux-kernel@vger.kernel.org,
Steven Rostedt <rostedt@goodmis.org>,
Gabriele Monaco <gmonaco@redhat.com>,
linux-trace-kernel@vger.kernel.org
Cc: Nam Cao <namcao@linutronix.de>, Wen Yang <wen.yang@linux.dev>
Subject: [PATCH v4 08/13] rv: Ensure synchronous cleanup for HA monitors
Date: Mon, 1 Jun 2026 17:38:35 +0200 [thread overview]
Message-ID: <20260601153840.124372-9-gmonaco@redhat.com> (raw)
In-Reply-To: <20260601153840.124372-1-gmonaco@redhat.com>
HA monitors may start timers, all cleanup functions currently stop the
timers asynchronously to avoid sleeping in the wrong context.
Nothing makes sure running callbacks terminate on cleanup.
Run the entire HA timer callback in an RCU read-side critical section,
this way we can simply synchronize_rcu() with any pending timer and are
sure any cleanup using kfree_rcu() runs after callbacks terminated.
Additionally make sure any unlikely callback running late won't run any
code if the monitor is marked as disabled or if destruction started.
Use memory barriers to serialise with racing resets.
Fixes: f5587d1b6ec9 ("rv: Add Hybrid Automata monitor type")
Fixes: 4a24127bd6cb ("rv: Add support for per-object monitors in DA/HA")
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
---
include/rv/da_monitor.h | 19 ++++++++++++++++---
include/rv/ha_monitor.h | 29 ++++++++++++++++++++++++++---
2 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/include/rv/da_monitor.h b/include/rv/da_monitor.h
index ec9bc88bd..1f440c781 100644
--- a/include/rv/da_monitor.h
+++ b/include/rv/da_monitor.h
@@ -57,6 +57,15 @@ static struct rv_monitor rv_this;
#define da_monitor_reset_hook(da_mon)
#endif
+/*
+ * Hook to allow the implementation of hybrid automata: define it with a
+ * function that waits for the termination of all monitors background
+ * activities (e.g. all timers). This hook can sleep.
+ */
+#ifndef da_monitor_sync_hook
+#define da_monitor_sync_hook()
+#endif
+
/*
* Type for the target id, default to int but can be overridden.
* A long type can work as hash table key (PER_OBJ) but will be downgraded to
@@ -82,7 +91,8 @@ static void react(enum states curr_state, enum events event)
static inline void da_monitor_reset_state(struct da_monitor *da_mon)
{
WRITE_ONCE(da_mon->monitoring, 0);
- da_mon->curr_state = model_get_initial_state();
+ /* Pair with load in __ha_monitor_timer_callback */
+ smp_store_release(&da_mon->curr_state, model_get_initial_state());
}
/*
@@ -205,6 +215,7 @@ static inline int da_monitor_init(void)
static inline void da_monitor_destroy(void)
{
da_monitor_reset_all();
+ da_monitor_sync_hook();
}
#elif RV_MON_TYPE == RV_MON_PER_CPU
@@ -270,6 +281,7 @@ static inline int da_monitor_init(void)
static inline void da_monitor_destroy(void)
{
da_monitor_reset_all();
+ da_monitor_sync_hook();
}
#elif RV_MON_TYPE == RV_MON_PER_TASK
@@ -367,6 +379,7 @@ static inline void da_monitor_destroy(void)
tracepoint_synchronize_unregister();
da_monitor_reset_all();
+ da_monitor_sync_hook();
rv_put_task_monitor_slot(task_mon_slot);
task_mon_slot = RV_PER_TASK_MONITOR_INIT;
@@ -573,13 +586,13 @@ static inline void da_monitor_destroy(void)
int bkt;
tracepoint_synchronize_unregister();
+ da_monitor_reset_all();
+ da_monitor_sync_hook();
/*
* This function is called after all probes are disabled and no longer
* pending, we can safely assume no concurrent user.
*/
- synchronize_rcu();
hash_for_each_safe(da_monitor_ht, bkt, tmp, mon_storage, node) {
- da_monitor_reset_hook(&mon_storage->rv.da_mon);
hash_del_rcu(&mon_storage->node);
kfree(mon_storage);
}
diff --git a/include/rv/ha_monitor.h b/include/rv/ha_monitor.h
index 4002b5247..28d3c74ca 100644
--- a/include/rv/ha_monitor.h
+++ b/include/rv/ha_monitor.h
@@ -37,6 +37,7 @@ static bool ha_monitor_handle_constraint(struct da_monitor *da_mon,
#define da_monitor_event_hook ha_monitor_handle_constraint
#define da_monitor_init_hook ha_monitor_init_env
#define da_monitor_reset_hook ha_monitor_reset_env
+#define da_monitor_sync_hook() synchronize_rcu()
#if !defined(HA_SKIP_AUTO_CLEANUP) && RV_MON_TYPE == RV_MON_PER_TASK
/*
@@ -136,10 +137,13 @@ static enum hrtimer_restart ha_monitor_timer_callback(struct hrtimer *hrtimer);
#define ha_get_ns() 0
#endif /* HA_CLK_NS */
+static bool ha_mon_destroying;
+
static int ha_monitor_init(void)
{
int ret;
+ WRITE_ONCE(ha_mon_destroying, false);
ret = da_monitor_init();
if (ret == 0)
ha_monitor_enable_hook();
@@ -148,6 +152,7 @@ static int ha_monitor_init(void)
static void ha_monitor_destroy(void)
{
+ WRITE_ONCE(ha_mon_destroying, true);
ha_monitor_disable_hook();
da_monitor_destroy();
}
@@ -288,12 +293,30 @@ static bool ha_monitor_handle_constraint(struct da_monitor *da_mon,
return false;
}
+/*
+ * __ha_monitor_timer_callback - generic callback representation
+ *
+ * This callback runs in an RCU read-side critical section to allow the
+ * destruction sequence to easily synchronize_rcu() with all pending timers
+ * after asynchronously disabling them. The ha_mon_destroying check ensures
+ * any callback entering the RCU section after synchronize_rcu() completes
+ * will see the flag and bail out immediately.
+ */
static inline void __ha_monitor_timer_callback(struct ha_monitor *ha_mon)
{
- enum states curr_state = READ_ONCE(ha_mon->da_mon.curr_state);
DECLARE_SEQ_BUF(env_string, ENV_BUFFER_SIZE);
- u64 time_ns = ha_get_ns();
-
+ enum states curr_state;
+ u64 time_ns;
+
+ guard(rcu)();
+ if (unlikely(READ_ONCE(ha_mon_destroying)))
+ return;
+ /* Ensure consistent curr_state if we race with da_monitor_reset */
+ curr_state = smp_load_acquire(&ha_mon->da_mon.curr_state);
+ if (unlikely(!da_monitor_handling_event(&ha_mon->da_mon)))
+ return;
+
+ time_ns = ha_get_ns();
ha_get_env_string(&env_string, ha_mon, time_ns);
ha_react(curr_state, EVENT_NONE, env_string.buffer);
ha_trace_error_env(ha_mon, model_get_state_name(curr_state),
--
2.54.0
next prev parent reply other threads:[~2026-06-01 15:39 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-01 15:38 [PATCH v4 00/13] rv: Fixes on Deterministic and Hybrid Automata Gabriele Monaco
2026-06-01 15:38 ` [PATCH v4 01/13] rv: Fix __user specifier usage in extract_params() Gabriele Monaco
2026-06-01 15:38 ` [PATCH v4 02/13] rv: Reset per-task DA monitors before releasing the slot Gabriele Monaco
2026-06-01 15:38 ` [PATCH v4 03/13] rv: Prevent in-flight per-task handlers from using invalid slots Gabriele Monaco
2026-06-01 15:38 ` [PATCH v4 04/13] rv: Ensure all pending probes terminate on per-obj monitor destroy Gabriele Monaco
2026-06-01 15:38 ` [PATCH v4 05/13] rv: Fix monitor start ordering and memory ordering for monitoring flag Gabriele Monaco
2026-06-01 15:38 ` [PATCH v4 06/13] rv: Do not rely on clean monitor when initialising HA Gabriele Monaco
2026-06-02 8:52 ` Nam Cao
2026-06-01 15:38 ` [PATCH v4 07/13] rv: Add automatic cleanup handlers for per-task HA monitors Gabriele Monaco
2026-06-01 15:38 ` Gabriele Monaco [this message]
2026-06-02 9:17 ` [PATCH v4 08/13] rv: Ensure synchronous cleanup for " Nam Cao
2026-06-01 15:38 ` [PATCH v4 09/13] rv: Prevent task migration while handling per-CPU events Gabriele Monaco
2026-06-01 15:38 ` [PATCH v4 10/13] rv: Use 0 to check preemption enabled in opid Gabriele Monaco
2026-06-01 15:38 ` [PATCH v4 11/13] verification/rvgen: Fix suffix strip in dot2k Gabriele Monaco
2026-06-01 15:38 ` [PATCH v4 12/13] rv: Fix read_lock scope in per-task DA cleanup Gabriele Monaco
2026-06-01 15:38 ` [PATCH v4 13/13] verification/rvgen: Generate cleanup hook for per-obj monitor Gabriele Monaco
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260601153840.124372-9-gmonaco@redhat.com \
--to=gmonaco@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=namcao@linutronix.de \
--cc=rostedt@goodmis.org \
--cc=wen.yang@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox