Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935/* SPDX-License-Identifier: GPL-2.0 *//* * Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org> * * Deterministic automata (DA) monitor functions, to be used together * with automata models in C generated by the rvgen tool. * * The rvgen tool is available at tools/verification/rvgen/ * * For further information, see: * Documentation/trace/rv/monitor_synthesis.rst */
#ifndef _RV_DA_MONITOR_H#define _RV_DA_MONITOR_H
#include <rv/automata.h>#include <linux/rv.h>#include <rv/kunit.h>#include <linux/stringify.h>#include <linux/bug.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/hashtable.h>
/* * Per-cpu variables require a unique name although static in some * configurations (e.g. alpha modules). */#define DA_MON_NAME CONCATENATE(da_mon_, MONITOR_NAME)
static struct rv_monitor rv_this;
/* * Hook to allow the implementation of hybrid automata: define it with a * function that takes curr_state, event and next_state and returns true if the * environment constraints (e.g. timing) are satisfied, false otherwise. */#ifndef da_monitor_event_hook#define da_monitor_event_hook(...) true#endif
/* * Hook to allow the implementation of hybrid automata: define it with a * function that takes the da_monitor and performs further initialisation * (e.g. reset set up timers). */#ifndef da_monitor_init_hook#define da_monitor_init_hook(da_mon)#endif
/* * Hook to allow the implementation of hybrid automata: define it with a * function that takes the da_monitor and performs further reset (e.g. reset * all clocks). */#ifndef da_monitor_reset_hook#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 * int in the event tracepoint. * Unused for implicit monitors. */#ifndef da_id_type#define da_id_type int#endif
static void react(enum states curr_state, enum events event){ rv_react(&rv_this, "rv: monitor %s does not allow event %s on state %s\n", __stringify(MONITOR_NAME), model_get_event_name(event), model_get_state_name(curr_state));}
/* * da_monitor_reset_state - reset a monitor and setting it to init state */static inline void da_monitor_reset_state(struct da_monitor *da_mon){ WRITE_ONCE(da_mon->monitoring, 0); /* Pair with load in __ha_monitor_timer_callback */ smp_store_release(&da_mon->curr_state, model_get_initial_state());}
/* * da_monitor_reset - reset a monitor and setting it to init state */static inline void da_monitor_reset(struct da_monitor *da_mon){ da_monitor_reset_hook(da_mon); da_monitor_reset_state(da_mon);}
/* * da_monitor_start - start monitoring * * The monitor will ignore all events until monitoring is set to true. This * function needs to be called to tell the monitor to start monitoring. */static inline void da_monitor_start(struct da_monitor *da_mon){ da_mon->curr_state = model_get_initial_state(); da_monitor_init_hook(da_mon); /* Pairs with smp_load_acquire in da_monitoring(). */ smp_store_release(&da_mon->monitoring, 1);}
/* * da_monitoring - returns true if the monitor is processing events */static inline bool da_monitoring(struct da_monitor *da_mon){ /* Pairs with smp_store_release in da_monitor_start(). */ return smp_load_acquire(&da_mon->monitoring);}
/* * da_monitor_enabled - checks if the monitor is enabled */static inline bool da_monitor_enabled(void){ /* global switch */ if (unlikely(!rv_monitoring_on())) return 0;
/* monitor enabled */ if (unlikely(!rv_this.enabled)) return 0;
return 1;}
/* * da_monitor_handling_event - checks if the monitor is ready to handle events */static inline bool da_monitor_handling_event(struct da_monitor *da_mon){ if (!da_monitor_enabled()) return 0;
/* monitor is actually monitoring */ if (unlikely(!da_monitoring(da_mon))) return 0;
return 1;}
#if RV_MON_TYPE == RV_MON_GLOBAL/* * Functions to define, init and get a global monitor. */
/* * global monitor (a single variable) */static struct da_monitor DA_MON_NAME;
/* * da_get_monitor - return the global monitor address */static struct da_monitor *da_get_monitor(void){ return &DA_MON_NAME;}
/* * __da_monitor_reset_all - reset the single monitor */static void __da_monitor_reset_all(void (*reset)(struct da_monitor *)){ reset(da_get_monitor());}
/* * da_monitor_reset_all - reset the single monitor */static void da_monitor_reset_all(void){ __da_monitor_reset_all(da_monitor_reset);}
/* * da_monitor_reset_state_all - reset the single monitor */static inline void da_monitor_reset_state_all(void){ __da_monitor_reset_all(da_monitor_reset_state);}
/* * da_monitor_init - initialize a monitor */static inline int da_monitor_init(void){ da_monitor_reset_state_all(); return 0;}
/* * da_monitor_destroy - destroy the monitor */static inline void da_monitor_destroy(void){ da_monitor_reset_all(); da_monitor_sync_hook();}
#ifndef da_implicit_guard#define da_implicit_guard()#endif
#elif RV_MON_TYPE == RV_MON_PER_CPU/* * Functions to define, init and get a per-cpu monitor. */
/* * per-cpu monitor variables */static DEFINE_PER_CPU(struct da_monitor, DA_MON_NAME);
/* * da_get_monitor - return current CPU monitor address */static struct da_monitor *da_get_monitor(void){ return this_cpu_ptr(&DA_MON_NAME);}
/* * __da_monitor_reset_all - reset all CPUs' monitor */static void __da_monitor_reset_all(void (*reset)(struct da_monitor *)){ struct da_monitor *da_mon; int cpu;
for_each_cpu(cpu, cpu_online_mask) { da_mon = per_cpu_ptr(&DA_MON_NAME, cpu); reset(da_mon); }}
/* * da_monitor_reset_all - reset all CPUs' monitor */static void da_monitor_reset_all(void){ __da_monitor_reset_all(da_monitor_reset);}
/* * da_monitor_reset_state_all - reset all CPUs' monitor */static inline void da_monitor_reset_state_all(void){ __da_monitor_reset_all(da_monitor_reset_state);}
/* * da_monitor_init - initialize all CPUs' monitor */static inline int da_monitor_init(void){ da_monitor_reset_state_all(); return 0;}
/* * da_monitor_destroy - destroy the monitor */static inline void da_monitor_destroy(void){ da_monitor_reset_all(); da_monitor_sync_hook();}
#ifndef da_implicit_guard#define da_implicit_guard() guard(migrate)()#endif
#elif RV_MON_TYPE == RV_MON_PER_TASK/* * Functions to define, init and get a per-task monitor. */
/* * The per-task monitor is stored a vector in the task struct. This variable * stores the position on the vector reserved for this monitor. */static int task_mon_slot = RV_PER_TASK_MONITOR_INIT;
/* * da_get_monitor - return the monitor in the allocated slot for tsk */static inline struct da_monitor *da_get_monitor(struct task_struct *tsk){ return &tsk->rv[task_mon_slot].da_mon;}
static inline void da_reset(struct task_struct *tsk){ da_monitor_reset(da_get_monitor(tsk));}
/* * da_get_target - return the task associated to the monitor */static inline struct task_struct *da_get_target(struct da_monitor *da_mon){ return container_of(da_mon, struct task_struct, rv[task_mon_slot].da_mon);}
/* * da_get_id - return the id associated to the monitor * * For per-task monitors, the id is the task's PID. */static inline da_id_type da_get_id(struct da_monitor *da_mon){ return da_get_target(da_mon)->pid;}
static void __da_monitor_reset_all(void (*reset)(struct da_monitor *)){ struct task_struct *g, *p; int cpu;
scoped_guard(read_lock, &tasklist_lock) { for_each_process_thread(g, p) reset(da_get_monitor(p)); } for_each_present_cpu(cpu) reset(da_get_monitor(idle_task(cpu)));}
static void da_monitor_reset_all(void){ __da_monitor_reset_all(da_monitor_reset);}
static inline void da_monitor_reset_state_all(void){ __da_monitor_reset_all(da_monitor_reset_state);}
/* * da_monitor_init - initialize the per-task monitor * * Try to allocate a slot in the task's vector of monitors. If there * is an available slot, use it and reset all task's monitor. */static int da_monitor_init(void){ int slot;
slot = rv_get_task_monitor_slot(); if (slot < 0 || slot >= RV_PER_TASK_MONITOR_INIT) return slot;
task_mon_slot = slot;
da_monitor_reset_state_all(); return 0;}
/* * da_monitor_destroy - return the allocated slot * * Wait for all in-flight handlers before returning the slot to avoid * out-of-bound accesses. */static inline void da_monitor_destroy(void){ if (task_mon_slot == RV_PER_TASK_MONITOR_INIT) { WARN_ONCE(1, "Disabling a disabled monitor: " __stringify(MONITOR_NAME)); return; }
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;}
#elif RV_MON_TYPE == RV_MON_PER_OBJ/* * Functions to define, init and get a per-object monitor. */
struct da_monitor_storage { da_id_type id; monitor_target target; union rv_task_monitor rv; struct hlist_node node; struct rcu_head rcu;};
#ifndef DA_MONITOR_HT_BITS#define DA_MONITOR_HT_BITS 10#endifstatic DEFINE_HASHTABLE(da_monitor_ht, DA_MONITOR_HT_BITS);
/* * da_create_empty_storage - pre-allocate an empty storage */static inline struct da_monitor_storage *da_create_empty_storage(da_id_type id){ struct da_monitor_storage *mon_storage;
mon_storage = kmalloc_nolock(sizeof(struct da_monitor_storage), __GFP_ZERO, NUMA_NO_NODE); if (!mon_storage) return NULL;
hash_add_rcu(da_monitor_ht, &mon_storage->node, id); mon_storage->id = id; return mon_storage;}
/* * da_create_storage - create the per-object storage * * The caller is responsible to synchronise writers, either with locks or * implicitly. For instance, if da_create_storage is only called from a single * event for target (e.g. sched_switch), it's safe to call this without locks. */static inline struct da_monitor *da_create_storage(da_id_type id, monitor_target target, struct da_monitor *da_mon){ struct da_monitor_storage *mon_storage;
if (da_mon) return da_mon;
mon_storage = da_create_empty_storage(id); if (!mon_storage) return NULL;
mon_storage->target = target; return &mon_storage->rv.da_mon;}
/* * __da_get_mon_storage - get the monitor storage from the hash table */static inline struct da_monitor_storage *__da_get_mon_storage(da_id_type id){ struct da_monitor_storage *mon_storage;
lockdep_assert_in_rcu_read_lock(); hash_for_each_possible_rcu(da_monitor_ht, mon_storage, node, id) { if (mon_storage->id == id) return mon_storage; }
return NULL;}
/* * da_get_monitor - return the monitor for target */static struct da_monitor *da_get_monitor(da_id_type id, monitor_target target){ struct da_monitor_storage *mon_storage;
mon_storage = __da_get_mon_storage(id); return mon_storage ? &mon_storage->rv.da_mon : NULL;}
/* * da_get_target - return the object associated to the monitor */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;}
/* * da_get_id - return the id associated to the monitor */static inline da_id_type da_get_id(struct da_monitor *da_mon){ return container_of(da_mon, struct da_monitor_storage, rv.da_mon)->id;}
/* * da_create_or_get - create the per-object storage if not already there * * This needs a lookup so should be guarded by RCU, the condition is checked * directly in da_create_storage() */static inline void da_create_or_get(da_id_type id, monitor_target target){ guard(rcu)(); da_create_storage(id, target, da_get_monitor(id, target));}
/* * da_fill_empty_storage - store the target in a pre-allocated storage * * Can be used as a substitute of da_create_storage when starting a monitor in * an environment where allocation is unsafe. */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; return da_mon;}
/* * da_get_target_by_id - return the object associated to the id */static inline monitor_target da_get_target_by_id(da_id_type id){ struct da_monitor_storage *mon_storage;
guard(rcu)(); mon_storage = __da_get_mon_storage(id);
if (unlikely(!mon_storage)) return NULL; return mon_storage->target;}
/* * da_destroy_storage - destroy the per-object storage * * The caller is responsible to synchronise writers, either with locks or * implicitly. For instance, if da_destroy_storage is called at sched_exit and * da_create_storage can never occur after that, it's safe to call this without * locks. * This function includes an RCU read-side critical section to synchronise * against da_monitor_destroy(). */static inline void da_destroy_storage(da_id_type id){ struct da_monitor_storage *mon_storage;
guard(rcu)(); mon_storage = __da_get_mon_storage(id);
if (!mon_storage) return; da_monitor_reset_hook(&mon_storage->rv.da_mon); hash_del_rcu(&mon_storage->node); kfree_rcu(mon_storage, rcu);}
static void __da_monitor_reset_all(void (*reset)(struct da_monitor *)){ struct da_monitor_storage *mon_storage; int bkt;
guard(rcu)(); hash_for_each_rcu(da_monitor_ht, bkt, mon_storage, node) reset(&mon_storage->rv.da_mon);}
static void da_monitor_reset_all(void){ __da_monitor_reset_all(da_monitor_reset);}
static inline void da_monitor_reset_state_all(void){ __da_monitor_reset_all(da_monitor_reset_state);}
static inline int da_monitor_init(void){ hash_init(da_monitor_ht); return 0;}
static inline void da_monitor_destroy(void){ struct da_monitor_storage *mon_storage; struct hlist_node *tmp; 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. */ hash_for_each_safe(da_monitor_ht, bkt, tmp, mon_storage, node) { hash_del_rcu(&mon_storage->node); kfree(mon_storage); }}
/* * Allow the per-object monitors to run allocation manually, necessary if the * start condition is in a context problematic for allocation (e.g. scheduling). * In such case, if the storage was pre-allocated without a target, set it now. */#ifdef DA_SKIP_AUTO_ALLOC#define da_prepare_storage da_fill_empty_storage#else#define da_prepare_storage da_create_storage#endif /* DA_SKIP_AUTO_ALLOC */
#endif /* RV_MON_TYPE */
#if RV_MON_TYPE == RV_MON_GLOBAL || RV_MON_TYPE == RV_MON_PER_CPU/* * Trace events for implicit monitors. Implicit monitor is the one which the * handler does not need to specify which da_monitor to manipulate. Examples * of implicit monitor are the per_cpu or the global ones. */
static inline void da_trace_event(struct da_monitor *da_mon, char *curr_state, char *event, char *next_state, bool is_final, da_id_type id){ CONCATENATE(trace_event_, MONITOR_NAME)(curr_state, event, next_state, is_final);}
static inline void da_trace_error(struct da_monitor *da_mon, char *curr_state, char *event, da_id_type id){ CONCATENATE(trace_error_, MONITOR_NAME)(curr_state, event);}
/* * da_get_id - unused for implicit monitors */static inline da_id_type da_get_id(struct da_monitor *da_mon){ return 0;}
#elif RV_MON_TYPE == RV_MON_PER_TASK || RV_MON_TYPE == RV_MON_PER_OBJ/* * Trace events for per_task/per_object monitors, report the target id. */
static inline void da_trace_event(struct da_monitor *da_mon, char *curr_state, char *event, char *next_state, bool is_final, da_id_type id){ CONCATENATE(trace_event_, MONITOR_NAME)(id, curr_state, event, next_state, is_final);}
static inline void da_trace_error(struct da_monitor *da_mon, char *curr_state, char *event, da_id_type id){ CONCATENATE(trace_error_, MONITOR_NAME)(id, curr_state, event);}#endif /* RV_MON_TYPE */
/* * da_event - handle an event for the da_mon * * This function is valid for both implicit and id monitors. * Retry in case there is a race between getting and setting the next state, * warn and reset the monitor if it runs out of retries. The monitor should be * able to handle various orders. */static inline bool da_event(struct da_monitor *da_mon, enum events event, da_id_type id){ enum states curr_state, next_state;
curr_state = READ_ONCE(da_mon->curr_state); for (int i = 0; i < MAX_DA_RETRY_RACING_EVENTS; i++) { next_state = model_get_next_state(curr_state, event); if (next_state == INVALID_STATE) { react(curr_state, event); da_trace_error(da_mon, model_get_state_name(curr_state), model_get_event_name(event), id); return false; } if (likely(try_cmpxchg(&da_mon->curr_state, &curr_state, next_state))) { if (!da_monitor_event_hook(da_mon, curr_state, event, next_state, id)) return false; da_trace_event(da_mon, model_get_state_name(curr_state), model_get_event_name(event), model_get_state_name(next_state), model_is_final_state(next_state), id); return true; } }
trace_rv_retries_error(__stringify(MONITOR_NAME), model_get_event_name(event)); pr_warn("rv: " __stringify(MAX_DA_RETRY_RACING_EVENTS) " retries reached for event %s, resetting monitor %s", model_get_event_name(event), __stringify(MONITOR_NAME)); return false;}
static inline void __da_handle_event_common(struct da_monitor *da_mon, enum events event, da_id_type id){ if (!da_event(da_mon, event, id)) da_monitor_reset(da_mon);}
static inline void __da_handle_event(struct da_monitor *da_mon, enum events event, da_id_type id){ if (da_monitor_handling_event(da_mon)) __da_handle_event_common(da_mon, event, id);}
static inline bool __da_handle_start_event(struct da_monitor *da_mon, enum events event, da_id_type id){ if (!da_monitor_enabled()) return 0; if (unlikely(!da_monitoring(da_mon))) { da_monitor_start(da_mon); return 0; }
__da_handle_event_common(da_mon, event, id);
return 1;}
static inline bool __da_handle_start_run_event(struct da_monitor *da_mon, enum events event, da_id_type id){ if (!da_monitor_enabled()) return 0; if (unlikely(!da_monitoring(da_mon))) da_monitor_start(da_mon);
__da_handle_event_common(da_mon, event, id);
return 1;}
#if RV_MON_TYPE == RV_MON_GLOBAL || RV_MON_TYPE == RV_MON_PER_CPU/* * Handle event for implicit monitor: da_get_monitor() will figure out * the monitor. */
/* * da_handle_event - handle an event */static inline void da_handle_event(enum events event){ da_implicit_guard(); __da_handle_event(da_get_monitor(), event, 0);}
/* * da_handle_start_event - start monitoring or handle event * * This function is used to notify the monitor that the system is returning * to the initial state, so the monitor can start monitoring in the next event. * Thus: * * If the monitor already started, handle the event. * If the monitor did not start yet, start the monitor but skip the event. */static inline bool da_handle_start_event(enum events event){ da_implicit_guard(); return __da_handle_start_event(da_get_monitor(), event, 0);}
/* * da_handle_start_run_event - start monitoring and handle event * * This function is used to notify the monitor that the system is in the * initial state, so the monitor can start monitoring and handling event. */static inline bool da_handle_start_run_event(enum events event){ da_implicit_guard(); return __da_handle_start_run_event(da_get_monitor(), event, 0);}
#elif RV_MON_TYPE == RV_MON_PER_TASK/* * Handle event for per task. */
/* * da_handle_event - handle an event */static inline void da_handle_event(struct task_struct *tsk, enum events event){ __da_handle_event(da_get_monitor(tsk), event, tsk->pid);}
/* * da_handle_start_event - start monitoring or handle event * * This function is used to notify the monitor that the system is returning * to the initial state, so the monitor can start monitoring in the next event. * Thus: * * If the monitor already started, handle the event. * If the monitor did not start yet, start the monitor but skip the event. */static inline bool da_handle_start_event(struct task_struct *tsk, enum events event){ return __da_handle_start_event(da_get_monitor(tsk), event, tsk->pid);}
/* * da_handle_start_run_event - start monitoring and handle event * * This function is used to notify the monitor that the system is in the * initial state, so the monitor can start monitoring and handling event. */static inline bool da_handle_start_run_event(struct task_struct *tsk, enum events event){ return __da_handle_start_run_event(da_get_monitor(tsk), event, tsk->pid);}
#elif RV_MON_TYPE == RV_MON_PER_OBJ/* * Handle event for per object. */
/* * da_handle_event - handle an event */static inline void da_handle_event(da_id_type id, monitor_target target, enum events event){ struct da_monitor *da_mon;
guard(rcu)(); da_mon = da_get_monitor(id, target); if (likely(da_mon)) __da_handle_event(da_mon, event, id);}
/* * da_handle_start_event - start monitoring or handle event * * This function is used to notify the monitor that the system is returning * to the initial state, so the monitor can start monitoring in the next event. * Thus: * * If the monitor already started, handle the event. * If the monitor did not start yet, start the monitor but skip the event. */static inline bool da_handle_start_event(da_id_type id, monitor_target target, enum events event){ struct da_monitor *da_mon;
guard(rcu)(); da_mon = da_get_monitor(id, target); da_mon = da_prepare_storage(id, target, da_mon); if (unlikely(!da_mon)) return 0; return __da_handle_start_event(da_mon, event, id);}
/* * da_handle_start_run_event - start monitoring and handle event * * This function is used to notify the monitor that the system is in the * initial state, so the monitor can start monitoring and handling event. */static inline bool da_handle_start_run_event(da_id_type id, monitor_target target, enum events event){ struct da_monitor *da_mon;
guard(rcu)(); da_mon = da_get_monitor(id, target); da_mon = da_prepare_storage(id, target, da_mon); if (unlikely(!da_mon)) return 0; return __da_handle_start_run_event(da_mon, event, id);}
static inline void da_reset(da_id_type id, monitor_target target){ struct da_monitor *da_mon;
guard(rcu)(); da_mon = da_get_monitor(id, target); if (likely(da_mon)) da_monitor_reset(da_mon);}#endif /* RV_MON_TYPE */
#if IS_ENABLED(CONFIG_RV_MONITORS_KUNIT_TEST)#if RV_MON_TYPE == RV_MON_PER_TASK#define RV_MON_OPS_INIT() { \ .rv_this = &rv_this, \ .is_per_task = true, \ .task_slot = &task_mon_slot, \ .task_reset = da_reset, \}#else#define RV_MON_OPS_INIT() { \ .rv_this = &rv_this, \ .monitor_init = da_monitor_init, \ .monitor_destroy = da_monitor_destroy, \}#endif /* RV_MON_TYPE */#endif /* CONFIG_RV_MONITORS_KUNIT_TEST */
#endif