Commit 30984ccf authored by Gabriele Monaco's avatar Gabriele Monaco
Browse files

rv: Refactor da_monitor to minimise macros



The da_monitor helper functions are generated from macros of the type:

DECLARE_DA_FUNCTION(name, type) \
static void da_func_x_##name(type arg) {} \
static void da_func_y_##name(type arg) {} \

This is good to minimise code duplication but the long macros made of
skipped end of lines is rather hard to parse. Since functions are
static, the advantage of naming them differently for each monitor is
minimal.

Refactor the da_monitor.h file to minimise macros, instead of declaring
functions from macros, we simply declare them with the same name for all
monitors (e.g. da_func_x) and for any remaining reference to the monitor
name (e.g. tracepoints, enums, global variables) we use the CONCATENATE
macro.
In this way the file is much easier to maintain while keeping the same
generality.
Functions depending on the monitor types are now conditionally compiled
according to the value of RV_MON_TYPE, which must be defined in the
monitor source.
The monitor type can be specified as in the original implementation,
although it's best to keep the default implementation (unsigned char) as
not all parts of code support larger data types, and likely there's no
need.

We keep the empty macro definitions to ease review of this change with
diff tools, but cleanup is required.

Also adapt existing monitors to keep the build working.

Reviewed-by: default avatarNam Cao <namcao@linutronix.de>
Link: https://lore.kernel.org/r/20251126104241.291258-2-gmonaco@redhat.com


Signed-off-by: default avatarGabriele Monaco <gmonaco@redhat.com>
parent 0f61b186
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -10,6 +10,10 @@
#define MAX_DA_NAME_LEN			32
#define MAX_DA_RETRY_RACING_EVENTS	3

#define RV_MON_GLOBAL   0
#define RV_MON_PER_CPU  1
#define RV_MON_PER_TASK 2

#ifdef CONFIG_RV
#include <linux/array_size.h>
#include <linux/bitops.h>
+73 −59
Original line number Diff line number Diff line
@@ -6,6 +6,20 @@
 * models in C generated by the dot2k tool.
 */

#ifndef MONITOR_NAME
#error "MONITOR_NAME macro is not defined. Did you include $(MODEL_NAME).h generated by rvgen?"
#endif

#ifndef type
#define type unsigned char
#endif

#define RV_AUTOMATON_NAME CONCATENATE(automaton_, MONITOR_NAME)
#define EVENT_MAX CONCATENATE(event_max_, MONITOR_NAME)
#define STATE_MAX CONCATENATE(state_max_, MONITOR_NAME)
#define events CONCATENATE(events_, MONITOR_NAME)
#define states CONCATENATE(states_, MONITOR_NAME)

/*
 * DECLARE_AUTOMATA_HELPERS - define a set of helper functions for automata
 *
@@ -13,63 +27,63 @@
 * as suffix for the functions and data. These functions will handle automaton
 * with data type 'type'.
 */
#define DECLARE_AUTOMATA_HELPERS(name, type)					\
										\
/*										\
 * model_get_state_name_##name - return the (string) name of the given state	\
 */ 										\
static char *model_get_state_name_##name(enum states_##name state)		\
{										\
	if ((state < 0) || (state >= state_max_##name))				\
		return "INVALID";						\
										\
	return automaton_##name.state_names[state];				\
}										\
										\
/*										\
 * model_get_event_name_##name - return the (string) name of the given event	\
 */										\
static char *model_get_event_name_##name(enum events_##name event)		\
{										\
	if ((event < 0) || (event >= event_max_##name))				\
		return "INVALID";						\
										\
	return automaton_##name.event_names[event];				\
}										\
										\
/*										\
 * model_get_initial_state_##name - return the automaton's initial state		\
 */										\
static inline type model_get_initial_state_##name(void)				\
{										\
	return automaton_##name.initial_state;					\
}										\
										\
/*										\
 * model_get_next_state_##name - process an automaton event occurrence		\
 *										\
 * Given the current state (curr_state) and the event (event), returns		\
 * the next state, or INVALID_STATE in case of error.				\
 */										\
static inline type model_get_next_state_##name(enum states_##name curr_state,	\
					       enum events_##name event)	\
{										\
	if ((curr_state < 0) || (curr_state >= state_max_##name))		\
		return INVALID_STATE;						\
										\
	if ((event < 0) || (event >= event_max_##name))				\
		return INVALID_STATE;						\
										\
	return automaton_##name.function[curr_state][event];			\
}										\
										\
/*										\
 * model_is_final_state_##name - check if the given state is a final state	\
 */										\
static inline bool model_is_final_state_##name(enum states_##name state)	\
{										\
	if ((state < 0) || (state >= state_max_##name))				\
		return 0;							\
										\
	return automaton_##name.final_states[state];				\
#define DECLARE_AUTOMATA_HELPERS(name, type)

/*
 * model_get_state_name - return the (string) name of the given state
 */
static char *model_get_state_name(enum states state)
{
	if ((state < 0) || (state >= STATE_MAX))
		return "INVALID";

	return RV_AUTOMATON_NAME.state_names[state];
}

/*
 * model_get_event_name - return the (string) name of the given event
 */
static char *model_get_event_name(enum events event)
{
	if ((event < 0) || (event >= EVENT_MAX))
		return "INVALID";

	return RV_AUTOMATON_NAME.event_names[event];
}

/*
 * model_get_initial_state - return the automaton's initial state
 */
static inline type model_get_initial_state(void)
{
	return RV_AUTOMATON_NAME.initial_state;
}

/*
 * model_get_next_state - process an automaton event occurrence
 *
 * Given the current state (curr_state) and the event (event), returns
 * the next state, or INVALID_STATE in case of error.
 */
static inline type model_get_next_state(enum states curr_state,
					       enum events event)
{
	if ((curr_state < 0) || (curr_state >= STATE_MAX))
		return INVALID_STATE;

	if ((event < 0) || (event >= EVENT_MAX))
		return INVALID_STATE;

	return RV_AUTOMATON_NAME.function[curr_state][event];
}

/*
 * model_is_final_state - check if the given state is a final state
 */
static inline bool model_is_final_state(enum states state)
{
	if ((state < 0) || (state >= STATE_MAX))
		return 0;

	return RV_AUTOMATON_NAME.final_states[state];
}
+443 −455

File changed.

Preview size limit exceeded, changes collapsed.

+14 −16
Original line number Diff line number Diff line
@@ -6,7 +6,6 @@
#include <linux/init.h>
#include <linux/rv.h>
#include <rv/instrumentation.h>
#include <rv/da_monitor.h>

#define MODULE_NAME "nrp"

@@ -15,17 +14,16 @@
#include <rv_trace.h>
#include <monitors/sched/sched.h>

#define RV_MON_TYPE RV_MON_PER_TASK
#include "nrp.h"

static struct rv_monitor rv_nrp;
DECLARE_DA_MON_PER_TASK(nrp, unsigned char);
#include <rv/da_monitor.h>

#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/trace/irq_vectors.h>

static void handle_vector_irq_entry(void *data, int vector)
{
	da_handle_event_nrp(current, irq_entry_nrp);
	da_handle_event(current, irq_entry_nrp);
}

static void attach_vector_irq(void)
@@ -60,7 +58,7 @@ static void detach_vector_irq(void) { }

static void handle_irq_entry(void *data, int irq, struct irqaction *action)
{
	da_handle_event_nrp(current, irq_entry_nrp);
	da_handle_event(current, irq_entry_nrp);
}

static void handle_sched_need_resched(void *data, struct task_struct *tsk,
@@ -72,22 +70,22 @@ static void handle_sched_need_resched(void *data, struct task_struct *tsk,
	 * which may not mirror the system state but makes the monitor simpler,
	 */
	if (tif == TIF_NEED_RESCHED)
		da_handle_start_event_nrp(tsk, sched_need_resched_nrp);
		da_handle_start_event(tsk, sched_need_resched_nrp);
}

static void handle_schedule_entry(void *data, bool preempt)
{
	if (preempt)
		da_handle_event_nrp(current, schedule_entry_preempt_nrp);
		da_handle_event(current, schedule_entry_preempt_nrp);
	else
		da_handle_event_nrp(current, schedule_entry_nrp);
		da_handle_event(current, schedule_entry_nrp);
}

static int enable_nrp(void)
{
	int retval;

	retval = da_monitor_init_nrp();
	retval = da_monitor_init();
	if (retval)
		return retval;

@@ -101,33 +99,33 @@ static int enable_nrp(void)

static void disable_nrp(void)
{
	rv_nrp.enabled = 0;
	rv_this.enabled = 0;

	rv_detach_trace_probe("nrp", irq_handler_entry, handle_irq_entry);
	rv_detach_trace_probe("nrp", sched_set_need_resched_tp, handle_sched_need_resched);
	rv_detach_trace_probe("nrp", sched_entry_tp, handle_schedule_entry);
	detach_vector_irq();

	da_monitor_destroy_nrp();
	da_monitor_destroy();
}

static struct rv_monitor rv_nrp = {
static struct rv_monitor rv_this = {
	.name = "nrp",
	.description = "need resched preempts.",
	.enable = enable_nrp,
	.disable = disable_nrp,
	.reset = da_monitor_reset_all_nrp,
	.reset = da_monitor_reset_all,
	.enabled = 0,
};

static int __init register_nrp(void)
{
	return rv_register_monitor(&rv_nrp, &rv_sched);
	return rv_register_monitor(&rv_this, &rv_sched);
}

static void __exit unregister_nrp(void)
{
	rv_unregister_monitor(&rv_nrp);
	rv_unregister_monitor(&rv_this);
}

module_init(register_nrp);
+2 −0
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@
 *   Documentation/trace/rv/deterministic_automata.rst
 */

#define MONITOR_NAME nrp

enum states_nrp {
	preempt_irq_nrp = 0,
	any_thread_running_nrp,
Loading