From: Gabriele Monaco <gmonaco@redhat.com>
To: wen.yang@linux.dev
Cc: Nam Cao <namcao@linutronix.de>,
linux-trace-kernel@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v7 00/14] rv: Add task latency over budget RV monitor
Date: Mon, 26 Oct 2026 14:06:13 +0100 [thread overview]
Message-ID: <2c2ecf44e7aa2d6a9bd8f926557bf745cad3d6fb.camel@redhat.com> (raw)
In-Reply-To: <462351c6a891d1a2d57d2589124caf939225f9b2.camel@redhat.com>
On Mon, 2026-10-26 at 12:05 +0100, Gabriele Monaco wrote:
> By the way there has been a running discussion about keeping the C files for
> the monitors as close as possible to the DOT representation, with a long-term
> goal to extend the DOT to represent everything and have logic represented
> there too (at least simple trace filters).
> ...
> These are general guidelines, the C files cannot yet be a 1-to-1 product of
> the model, but shouldn't be a completely different story either.
To push this even further, why don't we get the framework allocate also the
tlob_record ?
I played a bit to adapt the PER_OBJ things to accept non-pointer targets. Now
this is far from clean and is /not/ a recommendation over how the API should look
like, but it seems to work and simplified tlob even further.
Nothing forbids us to embed data with the monitor state also for other types in
the future (besides in-kernel PER_TASK, that must be fixed).
What do you think?
diff --git a/include/rv/da_monitor.h b/include/rv/da_monitor.h
index 04caaf529034..4677e19b228d 100644
--- a/include/rv/da_monitor.h
+++ b/include/rv/da_monitor.h
@@ -23,6 +23,17 @@
* must run in task context; other handlers only call
* da_handle_event() and never allocate.
* DA_ALLOC_MANUAL - caller pre-inserts storage; framework links the target.
+ *
+ * The target type: a PER_OBJ monitor usually typedefs monitor_target itself,
+ * as a pointer to the monitored object (borrowed: the object exists
+ * independently of the monitor and outlives the storage). A monitor whose
+ * target is monitor-owned data can instead define DA_OBJ_EMBEDDED_TYPE with
+ * a complete struct type: the framework then derives monitor_target as a
+ * pointer to it, embeds one instance in each per-object storage, and
+ * allocates and frees it together with the storage. On storage creation the
+ * caller-supplied target is shallow-copied into the storage before it is
+ * published, so it may be a fully initialised stack object. Do not define
+ * monitor_target by hand when using DA_OBJ_EMBEDDED_TYPE.
*/
#define DA_ALLOC_AUTO 0
#define DA_ALLOC_POOL 1
@@ -61,6 +72,10 @@
#include <linux/slab.h>
#include <linux/hashtable.h>
+#if defined(DA_OBJ_EMBEDDED_TYPE) && RV_MON_TYPE != RV_MON_PER_OBJ
+#error "DA_OBJ_EMBEDDED_TYPE is only supported by RV_MON_PER_OBJ monitors"
+#endif
+
/*
* Per-cpu variables require a unique name although static in some
* configurations (e.g. alpha modules).
@@ -463,9 +478,24 @@ static inline void da_monitor_destroy(void)
* Functions to define, init and get a per-object monitor.
*/
+#ifdef DA_OBJ_EMBEDDED_TYPE
+/*
+ * Framework-owned target: one instance is embedded in each storage and
+ * allocated/freed with it. monitor_target keeps pointer semantics, but
+ * da_get_target() points into the storage rather than to a borrowed object.
+ * The header derives the typedef: do not define monitor_target by hand.
+ */
+typedef DA_OBJ_EMBEDDED_TYPE *monitor_target;
+#endif
+
struct da_monitor_storage {
da_id_type id;
+#ifdef DA_OBJ_EMBEDDED_TYPE
+ DA_OBJ_EMBEDDED_TYPE target;
+ bool filled;
+#else
monitor_target target;
+#endif
union rv_task_monitor rv;
struct hlist_node node;
struct rcu_head rcu;
@@ -476,6 +506,38 @@ struct da_monitor_storage {
#endif
static DEFINE_HASHTABLE(da_monitor_ht, DA_MONITOR_HT_BITS);
+#ifdef DA_OBJ_EMBEDDED_TYPE
+
+#define TARGET_PTR(storage) &storage->target
+
+static inline bool da_storage_is_empty(struct da_monitor_storage *mon_storage)
+{
+ return !smp_load_acquire(&mon_storage->filled);
+}
+static inline void da_storage_set_target(struct da_monitor_storage *mon_storage,
+ monitor_target target)
+{
+ if (WARN_ON_ONCE(!target))
+ return;
+
+ memcpy(&mon_storage->target, target, sizeof(mon_storage->target));
+ smp_store_release(&mon_storage->filled, true);
+}
+#else
+
+#define TARGET_PTR(storage) storage->target
+
+static inline bool da_storage_is_empty(struct da_monitor_storage *mon_storage)
+{
+ return !TARGET_PTR(mon_storage);
+}
+static inline void da_storage_set_target(struct da_monitor_storage *mon_storage,
+ monitor_target target)
+{
+ mon_storage->target = target;
+}
+#endif
+
/*
* da_create_empty_storage - pre-allocate an empty storage
*/
@@ -513,7 +575,7 @@ static inline struct da_monitor *da_create_storage(da_id_type id,
if (!mon_storage)
return NULL;
- mon_storage->target = target;
+ da_storage_set_target(mon_storage, target);
return &mon_storage->rv.da_mon;
}
@@ -549,7 +611,7 @@ static struct da_monitor *da_get_monitor(da_id_type id, monitor_target target)
*/
static inline monitor_target da_get_target(struct da_monitor *da_mon)
{
- return container_of(da_mon, struct da_monitor_storage, rv.da_mon)->target;
+ return TARGET_PTR(container_of(da_mon, struct da_monitor_storage, rv.da_mon));
}
/*
@@ -582,8 +644,11 @@ static inline struct da_monitor *da_fill_empty_storage(da_id_type id,
monitor_target target,
struct da_monitor *da_mon)
{
- if (unlikely(da_mon && !da_get_target(da_mon)))
- container_of(da_mon, struct da_monitor_storage, rv.da_mon)->target = target;
+ struct da_monitor_storage *mon_storage =
+ container_of(da_mon, struct da_monitor_storage, rv.da_mon);
+
+ if (unlikely(da_mon && da_storage_is_empty(mon_storage)))
+ da_storage_set_target(mon_storage, target);
return da_mon;
}
@@ -599,7 +664,7 @@ static inline monitor_target da_get_target_by_id(da_id_type id)
if (unlikely(!mon_storage))
return NULL;
- return mon_storage->target;
+ return TARGET_PTR(mon_storage);
}
static void da_kfree_cb(struct rcu_head *head)
@@ -645,7 +710,7 @@ da_create_pool_storage(da_id_type id, monitor_target target,
memset(mon_storage, 0, sizeof(*mon_storage));
mon_storage->id = id;
- mon_storage->target = target;
+ da_storage_set_target(mon_storage, target);
hash_add_rcu(da_monitor_ht, &mon_storage->node, id);
return &mon_storage->rv.da_mon;
prev parent reply other threads:[~2026-10-26 13:06 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-11 19:39 wen.yang
2026-10-11 19:39 ` [PATCH v7 01/14] rv: Force environment reset action on HA monitor start wen.yang
2026-10-11 19:39 ` [PATCH v7 02/14] rv: Fix ha_monitor timer and invariant underflow wen.yang
2026-10-26 9:21 ` Gabriele Monaco
2026-10-11 19:39 ` [PATCH v7 03/14] rv: Add a KUnit test for the HA timer underflow wen.yang
2026-10-12 7:47 ` kernel test robot
2026-10-12 9:27 ` kernel test robot
2026-10-12 11:18 ` kernel test robot
2026-10-26 9:43 ` Gabriele Monaco
2026-10-11 19:39 ` [PATCH v7 04/14] rv: Disarm HA timers on the storage free path wen.yang
2026-10-26 9:57 ` Gabriele Monaco
2026-10-11 19:39 ` [PATCH v7 05/14] rv: Add a KUnit test for " wen.yang
2026-10-11 19:39 ` [PATCH v7 06/14] rv: Make da_monitor_reset_hook and EVENT_NONE_LBL overridable wen.yang
2026-10-11 19:39 ` [PATCH v7 07/14] rv: Introduce DA_MON_ALLOCATION_STRATEGY wen.yang
2026-10-11 19:39 ` [PATCH v7 08/14] rv: Add per-object teardown hook da_extra_cleanup wen.yang
2026-10-11 19:39 ` [PATCH v7 09/14] rv: Add generic uprobe infrastructure for RV monitors wen.yang
2026-10-11 19:39 ` [PATCH v7 10/14] rv: Add tlob model DOT file wen.yang
2026-10-11 19:39 ` [PATCH v7 11/14] rv: Add tlob hybrid automaton monitor wen.yang
2026-10-11 19:39 ` [PATCH v7 12/14] rv: Add KUnit tests for the tlob monitor wen.yang
2026-10-11 19:39 ` [PATCH v7 13/14] selftests/verification: Add tlob selftests wen.yang
2026-10-11 19:39 ` [PATCH v7 14/14] selftests/ftrace: Walk up parent dirs to find test.d/functions wen.yang
2026-10-12 11:58 ` [PATCH v7 00/14] rv: Add task latency over budget RV monitor Gabriele Monaco
2026-10-19 19:18 ` Wen Yang
2026-10-19 19:48 ` Steven Rostedt
2026-10-20 15:33 ` Gabriele Monaco
2026-10-20 15:30 ` Gabriele Monaco
2026-10-26 11:05 ` Gabriele Monaco
2026-10-26 13:06 ` Gabriele Monaco [this message]
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=2c2ecf44e7aa2d6a9bd8f926557bf745cad3d6fb.camel@redhat.com \
--to=gmonaco@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=namcao@linutronix.de \
--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
all inboxes | Powered by JetHome®