projects/linux·blob master · refs

934 lines · 23.1 KiB

1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <[email protected]>
4 *
5 * Deterministic automata (DA) monitor functions, to be used together
6 * with automata models in C generated by the rvgen tool.
7 *
8 * The rvgen tool is available at tools/verification/rvgen/
9 *
10 * For further information, see:
11 * Documentation/trace/rv/monitor_synthesis.rst
12 */
13
14#ifndef _RV_DA_MONITOR_H
15#define _RV_DA_MONITOR_H
16
17#include <rv/automata.h>
18#include <linux/rv.h>
19#include <rv/kunit.h>
20#include <linux/stringify.h>
21#include <linux/bug.h>
22#include <linux/sched.h>
23#include <linux/slab.h>
24#include <linux/hashtable.h>
25
26/*
27 * Per-cpu variables require a unique name although static in some
28 * configurations (e.g. alpha modules).
29 */
30#define DA_MON_NAME CONCATENATE(da_mon_, MONITOR_NAME)
31
32static struct rv_monitor rv_this;
33
34/*
35 * Hook to allow the implementation of hybrid automata: define it with a
36 * function that takes curr_state, event and next_state and returns true if the
37 * environment constraints (e.g. timing) are satisfied, false otherwise.
38 */
39#ifndef da_monitor_event_hook
40#define da_monitor_event_hook(...) true
41#endif
42
43/*
44 * Hook to allow the implementation of hybrid automata: define it with a
45 * function that takes the da_monitor and performs further initialisation
46 * (e.g. reset set up timers).
47 */
48#ifndef da_monitor_init_hook
49#define da_monitor_init_hook(da_mon)
50#endif
51
52/*
53 * Hook to allow the implementation of hybrid automata: define it with a
54 * function that takes the da_monitor and performs further reset (e.g. reset
55 * all clocks).
56 */
57#ifndef da_monitor_reset_hook
58#define da_monitor_reset_hook(da_mon)
59#endif
60
61/*
62 * Hook to allow the implementation of hybrid automata: define it with a
63 * function that waits for the termination of all monitors background
64 * activities (e.g. all timers). This hook can sleep.
65 */
66#ifndef da_monitor_sync_hook
67#define da_monitor_sync_hook()
68#endif
69
70/*
71 * Type for the target id, default to int but can be overridden.
72 * A long type can work as hash table key (PER_OBJ) but will be downgraded to
73 * int in the event tracepoint.
74 * Unused for implicit monitors.
75 */
76#ifndef da_id_type
77#define da_id_type int
78#endif
79
80static void react(enum states curr_state, enum events event)
81{
82 rv_react(&rv_this,
83 "rv: monitor %s does not allow event %s on state %s\n",
84 __stringify(MONITOR_NAME),
85 model_get_event_name(event),
86 model_get_state_name(curr_state));
87}
88
89/*
90 * da_monitor_reset_state - reset a monitor and setting it to init state
91 */
92static inline void da_monitor_reset_state(struct da_monitor *da_mon)
93{
94 WRITE_ONCE(da_mon->monitoring, 0);
95 /* Pair with load in __ha_monitor_timer_callback */
96 smp_store_release(&da_mon->curr_state, model_get_initial_state());
97}
98
99/*
100 * da_monitor_reset - reset a monitor and setting it to init state
101 */
102static inline void da_monitor_reset(struct da_monitor *da_mon)
103{
104 da_monitor_reset_hook(da_mon);
105 da_monitor_reset_state(da_mon);
106}
107
108/*
109 * da_monitor_start - start monitoring
110 *
111 * The monitor will ignore all events until monitoring is set to true. This
112 * function needs to be called to tell the monitor to start monitoring.
113 */
114static inline void da_monitor_start(struct da_monitor *da_mon)
115{
116 da_mon->curr_state = model_get_initial_state();
117 da_monitor_init_hook(da_mon);
118 /* Pairs with smp_load_acquire in da_monitoring(). */
119 smp_store_release(&da_mon->monitoring, 1);
120}
121
122/*
123 * da_monitoring - returns true if the monitor is processing events
124 */
125static inline bool da_monitoring(struct da_monitor *da_mon)
126{
127 /* Pairs with smp_store_release in da_monitor_start(). */
128 return smp_load_acquire(&da_mon->monitoring);
129}
130
131/*
132 * da_monitor_enabled - checks if the monitor is enabled
133 */
134static inline bool da_monitor_enabled(void)
135{
136 /* global switch */
137 if (unlikely(!rv_monitoring_on()))
138 return 0;
139
140 /* monitor enabled */
141 if (unlikely(!rv_this.enabled))
142 return 0;
143
144 return 1;
145}
146
147/*
148 * da_monitor_handling_event - checks if the monitor is ready to handle events
149 */
150static inline bool da_monitor_handling_event(struct da_monitor *da_mon)
151{
152 if (!da_monitor_enabled())
153 return 0;
154
155 /* monitor is actually monitoring */
156 if (unlikely(!da_monitoring(da_mon)))
157 return 0;
158
159 return 1;
160}
161
162#if RV_MON_TYPE == RV_MON_GLOBAL
163/*
164 * Functions to define, init and get a global monitor.
165 */
166
167/*
168 * global monitor (a single variable)
169 */
170static struct da_monitor DA_MON_NAME;
171
172/*
173 * da_get_monitor - return the global monitor address
174 */
175static struct da_monitor *da_get_monitor(void)
176{
177 return &DA_MON_NAME;
178}
179
180/*
181 * __da_monitor_reset_all - reset the single monitor
182 */
183static void __da_monitor_reset_all(void (*reset)(struct da_monitor *))
184{
185 reset(da_get_monitor());
186}
187
188/*
189 * da_monitor_reset_all - reset the single monitor
190 */
191static void da_monitor_reset_all(void)
192{
193 __da_monitor_reset_all(da_monitor_reset);
194}
195
196/*
197 * da_monitor_reset_state_all - reset the single monitor
198 */
199static inline void da_monitor_reset_state_all(void)
200{
201 __da_monitor_reset_all(da_monitor_reset_state);
202}
203
204/*
205 * da_monitor_init - initialize a monitor
206 */
207static inline int da_monitor_init(void)
208{
209 da_monitor_reset_state_all();
210 return 0;
211}
212
213/*
214 * da_monitor_destroy - destroy the monitor
215 */
216static inline void da_monitor_destroy(void)
217{
218 da_monitor_reset_all();
219 da_monitor_sync_hook();
220}
221
222#ifndef da_implicit_guard
223#define da_implicit_guard()
224#endif
225
226#elif RV_MON_TYPE == RV_MON_PER_CPU
227/*
228 * Functions to define, init and get a per-cpu monitor.
229 */
230
231/*
232 * per-cpu monitor variables
233 */
234static DEFINE_PER_CPU(struct da_monitor, DA_MON_NAME);
235
236/*
237 * da_get_monitor - return current CPU monitor address
238 */
239static struct da_monitor *da_get_monitor(void)
240{
241 return this_cpu_ptr(&DA_MON_NAME);
242}
243
244/*
245 * __da_monitor_reset_all - reset all CPUs' monitor
246 */
247static void __da_monitor_reset_all(void (*reset)(struct da_monitor *))
248{
249 struct da_monitor *da_mon;
250 int cpu;
251
252 for_each_cpu(cpu, cpu_online_mask) {
253 da_mon = per_cpu_ptr(&DA_MON_NAME, cpu);
254 reset(da_mon);
255 }
256}
257
258/*
259 * da_monitor_reset_all - reset all CPUs' monitor
260 */
261static void da_monitor_reset_all(void)
262{
263 __da_monitor_reset_all(da_monitor_reset);
264}
265
266/*
267 * da_monitor_reset_state_all - reset all CPUs' monitor
268 */
269static inline void da_monitor_reset_state_all(void)
270{
271 __da_monitor_reset_all(da_monitor_reset_state);
272}
273
274/*
275 * da_monitor_init - initialize all CPUs' monitor
276 */
277static inline int da_monitor_init(void)
278{
279 da_monitor_reset_state_all();
280 return 0;
281}
282
283/*
284 * da_monitor_destroy - destroy the monitor
285 */
286static inline void da_monitor_destroy(void)
287{
288 da_monitor_reset_all();
289 da_monitor_sync_hook();
290}
291
292#ifndef da_implicit_guard
293#define da_implicit_guard() guard(migrate)()
294#endif
295
296#elif RV_MON_TYPE == RV_MON_PER_TASK
297/*
298 * Functions to define, init and get a per-task monitor.
299 */
300
301/*
302 * The per-task monitor is stored a vector in the task struct. This variable
303 * stores the position on the vector reserved for this monitor.
304 */
305static int task_mon_slot = RV_PER_TASK_MONITOR_INIT;
306
307/*
308 * da_get_monitor - return the monitor in the allocated slot for tsk
309 */
310static inline struct da_monitor *da_get_monitor(struct task_struct *tsk)
311{
312 return &tsk->rv[task_mon_slot].da_mon;
313}
314
315static inline void da_reset(struct task_struct *tsk)
316{
317 da_monitor_reset(da_get_monitor(tsk));
318}
319
320/*
321 * da_get_target - return the task associated to the monitor
322 */
323static inline struct task_struct *da_get_target(struct da_monitor *da_mon)
324{
325 return container_of(da_mon, struct task_struct, rv[task_mon_slot].da_mon);
326}
327
328/*
329 * da_get_id - return the id associated to the monitor
330 *
331 * For per-task monitors, the id is the task's PID.
332 */
333static inline da_id_type da_get_id(struct da_monitor *da_mon)
334{
335 return da_get_target(da_mon)->pid;
336}
337
338static void __da_monitor_reset_all(void (*reset)(struct da_monitor *))
339{
340 struct task_struct *g, *p;
341 int cpu;
342
343 scoped_guard(read_lock, &tasklist_lock) {
344 for_each_process_thread(g, p)
345 reset(da_get_monitor(p));
346 }
347 for_each_present_cpu(cpu)
348 reset(da_get_monitor(idle_task(cpu)));
349}
350
351static void da_monitor_reset_all(void)
352{
353 __da_monitor_reset_all(da_monitor_reset);
354}
355
356static inline void da_monitor_reset_state_all(void)
357{
358 __da_monitor_reset_all(da_monitor_reset_state);
359}
360
361/*
362 * da_monitor_init - initialize the per-task monitor
363 *
364 * Try to allocate a slot in the task's vector of monitors. If there
365 * is an available slot, use it and reset all task's monitor.
366 */
367static int da_monitor_init(void)
368{
369 int slot;
370
371 slot = rv_get_task_monitor_slot();
372 if (slot < 0 || slot >= RV_PER_TASK_MONITOR_INIT)
373 return slot;
374
375 task_mon_slot = slot;
376
377 da_monitor_reset_state_all();
378 return 0;
379}
380
381/*
382 * da_monitor_destroy - return the allocated slot
383 *
384 * Wait for all in-flight handlers before returning the slot to avoid
385 * out-of-bound accesses.
386 */
387static inline void da_monitor_destroy(void)
388{
389 if (task_mon_slot == RV_PER_TASK_MONITOR_INIT) {
390 WARN_ONCE(1, "Disabling a disabled monitor: " __stringify(MONITOR_NAME));
391 return;
392 }
393
394 tracepoint_synchronize_unregister();
395 da_monitor_reset_all();
396 da_monitor_sync_hook();
397
398 rv_put_task_monitor_slot(task_mon_slot);
399 task_mon_slot = RV_PER_TASK_MONITOR_INIT;
400}
401
402#elif RV_MON_TYPE == RV_MON_PER_OBJ
403/*
404 * Functions to define, init and get a per-object monitor.
405 */
406
407struct da_monitor_storage {
408 da_id_type id;
409 monitor_target target;
410 union rv_task_monitor rv;
411 struct hlist_node node;
412 struct rcu_head rcu;
413};
414
415#ifndef DA_MONITOR_HT_BITS
416#define DA_MONITOR_HT_BITS 10
417#endif
418static DEFINE_HASHTABLE(da_monitor_ht, DA_MONITOR_HT_BITS);
419
420/*
421 * da_create_empty_storage - pre-allocate an empty storage
422 */
423static inline struct da_monitor_storage *da_create_empty_storage(da_id_type id)
424{
425 struct da_monitor_storage *mon_storage;
426
427 mon_storage = kmalloc_nolock(sizeof(struct da_monitor_storage),
428 __GFP_ZERO, NUMA_NO_NODE);
429 if (!mon_storage)
430 return NULL;
431
432 hash_add_rcu(da_monitor_ht, &mon_storage->node, id);
433 mon_storage->id = id;
434 return mon_storage;
435}
436
437/*
438 * da_create_storage - create the per-object storage
439 *
440 * The caller is responsible to synchronise writers, either with locks or
441 * implicitly. For instance, if da_create_storage is only called from a single
442 * event for target (e.g. sched_switch), it's safe to call this without locks.
443 */
444static inline struct da_monitor *da_create_storage(da_id_type id,
445 monitor_target target,
446 struct da_monitor *da_mon)
447{
448 struct da_monitor_storage *mon_storage;
449
450 if (da_mon)
451 return da_mon;
452
453 mon_storage = da_create_empty_storage(id);
454 if (!mon_storage)
455 return NULL;
456
457 mon_storage->target = target;
458 return &mon_storage->rv.da_mon;
459}
460
461/*
462 * __da_get_mon_storage - get the monitor storage from the hash table
463 */
464static inline struct da_monitor_storage *__da_get_mon_storage(da_id_type id)
465{
466 struct da_monitor_storage *mon_storage;
467
468 lockdep_assert_in_rcu_read_lock();
469 hash_for_each_possible_rcu(da_monitor_ht, mon_storage, node, id) {
470 if (mon_storage->id == id)
471 return mon_storage;
472 }
473
474 return NULL;
475}
476
477/*
478 * da_get_monitor - return the monitor for target
479 */
480static struct da_monitor *da_get_monitor(da_id_type id, monitor_target target)
481{
482 struct da_monitor_storage *mon_storage;
483
484 mon_storage = __da_get_mon_storage(id);
485 return mon_storage ? &mon_storage->rv.da_mon : NULL;
486}
487
488/*
489 * da_get_target - return the object associated to the monitor
490 */
491static inline monitor_target da_get_target(struct da_monitor *da_mon)
492{
493 return container_of(da_mon, struct da_monitor_storage, rv.da_mon)->target;
494}
495
496/*
497 * da_get_id - return the id associated to the monitor
498 */
499static inline da_id_type da_get_id(struct da_monitor *da_mon)
500{
501 return container_of(da_mon, struct da_monitor_storage, rv.da_mon)->id;
502}
503
504/*
505 * da_create_or_get - create the per-object storage if not already there
506 *
507 * This needs a lookup so should be guarded by RCU, the condition is checked
508 * directly in da_create_storage()
509 */
510static inline void da_create_or_get(da_id_type id, monitor_target target)
511{
512 guard(rcu)();
513 da_create_storage(id, target, da_get_monitor(id, target));
514}
515
516/*
517 * da_fill_empty_storage - store the target in a pre-allocated storage
518 *
519 * Can be used as a substitute of da_create_storage when starting a monitor in
520 * an environment where allocation is unsafe.
521 */
522static inline struct da_monitor *da_fill_empty_storage(da_id_type id,
523 monitor_target target,
524 struct da_monitor *da_mon)
525{
526 if (unlikely(da_mon && !da_get_target(da_mon)))
527 container_of(da_mon, struct da_monitor_storage, rv.da_mon)->target = target;
528 return da_mon;
529}
530
531/*
532 * da_get_target_by_id - return the object associated to the id
533 */
534static inline monitor_target da_get_target_by_id(da_id_type id)
535{
536 struct da_monitor_storage *mon_storage;
537
538 guard(rcu)();
539 mon_storage = __da_get_mon_storage(id);
540
541 if (unlikely(!mon_storage))
542 return NULL;
543 return mon_storage->target;
544}
545
546/*
547 * da_destroy_storage - destroy the per-object storage
548 *
549 * The caller is responsible to synchronise writers, either with locks or
550 * implicitly. For instance, if da_destroy_storage is called at sched_exit and
551 * da_create_storage can never occur after that, it's safe to call this without
552 * locks.
553 * This function includes an RCU read-side critical section to synchronise
554 * against da_monitor_destroy().
555 */
556static inline void da_destroy_storage(da_id_type id)
557{
558 struct da_monitor_storage *mon_storage;
559
560 guard(rcu)();
561 mon_storage = __da_get_mon_storage(id);
562
563 if (!mon_storage)
564 return;
565 da_monitor_reset_hook(&mon_storage->rv.da_mon);
566 hash_del_rcu(&mon_storage->node);
567 kfree_rcu(mon_storage, rcu);
568}
569
570static void __da_monitor_reset_all(void (*reset)(struct da_monitor *))
571{
572 struct da_monitor_storage *mon_storage;
573 int bkt;
574
575 guard(rcu)();
576 hash_for_each_rcu(da_monitor_ht, bkt, mon_storage, node)
577 reset(&mon_storage->rv.da_mon);
578}
579
580static void da_monitor_reset_all(void)
581{
582 __da_monitor_reset_all(da_monitor_reset);
583}
584
585static inline void da_monitor_reset_state_all(void)
586{
587 __da_monitor_reset_all(da_monitor_reset_state);
588}
589
590static inline int da_monitor_init(void)
591{
592 hash_init(da_monitor_ht);
593 return 0;
594}
595
596static inline void da_monitor_destroy(void)
597{
598 struct da_monitor_storage *mon_storage;
599 struct hlist_node *tmp;
600 int bkt;
601
602 tracepoint_synchronize_unregister();
603 da_monitor_reset_all();
604 da_monitor_sync_hook();
605 /*
606 * This function is called after all probes are disabled and no longer
607 * pending, we can safely assume no concurrent user.
608 */
609 hash_for_each_safe(da_monitor_ht, bkt, tmp, mon_storage, node) {
610 hash_del_rcu(&mon_storage->node);
611 kfree(mon_storage);
612 }
613}
614
615/*
616 * Allow the per-object monitors to run allocation manually, necessary if the
617 * start condition is in a context problematic for allocation (e.g. scheduling).
618 * In such case, if the storage was pre-allocated without a target, set it now.
619 */
620#ifdef DA_SKIP_AUTO_ALLOC
621#define da_prepare_storage da_fill_empty_storage
622#else
623#define da_prepare_storage da_create_storage
624#endif /* DA_SKIP_AUTO_ALLOC */
625
626#endif /* RV_MON_TYPE */
627
628#if RV_MON_TYPE == RV_MON_GLOBAL || RV_MON_TYPE == RV_MON_PER_CPU
629/*
630 * Trace events for implicit monitors. Implicit monitor is the one which the
631 * handler does not need to specify which da_monitor to manipulate. Examples
632 * of implicit monitor are the per_cpu or the global ones.
633 */
634
635static inline void da_trace_event(struct da_monitor *da_mon,
636 char *curr_state, char *event,
637 char *next_state, bool is_final,
638 da_id_type id)
639{
640 CONCATENATE(trace_event_, MONITOR_NAME)(curr_state, event, next_state,
641 is_final);
642}
643
644static inline void da_trace_error(struct da_monitor *da_mon,
645 char *curr_state, char *event,
646 da_id_type id)
647{
648 CONCATENATE(trace_error_, MONITOR_NAME)(curr_state, event);
649}
650
651/*
652 * da_get_id - unused for implicit monitors
653 */
654static inline da_id_type da_get_id(struct da_monitor *da_mon)
655{
656 return 0;
657}
658
659#elif RV_MON_TYPE == RV_MON_PER_TASK || RV_MON_TYPE == RV_MON_PER_OBJ
660/*
661 * Trace events for per_task/per_object monitors, report the target id.
662 */
663
664static inline void da_trace_event(struct da_monitor *da_mon,
665 char *curr_state, char *event,
666 char *next_state, bool is_final,
667 da_id_type id)
668{
669 CONCATENATE(trace_event_, MONITOR_NAME)(id, curr_state, event,
670 next_state, is_final);
671}
672
673static inline void da_trace_error(struct da_monitor *da_mon,
674 char *curr_state, char *event,
675 da_id_type id)
676{
677 CONCATENATE(trace_error_, MONITOR_NAME)(id, curr_state, event);
678}
679#endif /* RV_MON_TYPE */
680
681/*
682 * da_event - handle an event for the da_mon
683 *
684 * This function is valid for both implicit and id monitors.
685 * Retry in case there is a race between getting and setting the next state,
686 * warn and reset the monitor if it runs out of retries. The monitor should be
687 * able to handle various orders.
688 */
689static inline bool da_event(struct da_monitor *da_mon, enum events event, da_id_type id)
690{
691 enum states curr_state, next_state;
692
693 curr_state = READ_ONCE(da_mon->curr_state);
694 for (int i = 0; i < MAX_DA_RETRY_RACING_EVENTS; i++) {
695 next_state = model_get_next_state(curr_state, event);
696 if (next_state == INVALID_STATE) {
697 react(curr_state, event);
698 da_trace_error(da_mon, model_get_state_name(curr_state),
699 model_get_event_name(event), id);
700 return false;
701 }
702 if (likely(try_cmpxchg(&da_mon->curr_state, &curr_state, next_state))) {
703 if (!da_monitor_event_hook(da_mon, curr_state, event, next_state, id))
704 return false;
705 da_trace_event(da_mon, model_get_state_name(curr_state),
706 model_get_event_name(event),
707 model_get_state_name(next_state),
708 model_is_final_state(next_state), id);
709 return true;
710 }
711 }
712
713 trace_rv_retries_error(__stringify(MONITOR_NAME), model_get_event_name(event));
714 pr_warn("rv: " __stringify(MAX_DA_RETRY_RACING_EVENTS)
715 " retries reached for event %s, resetting monitor %s",
716 model_get_event_name(event), __stringify(MONITOR_NAME));
717 return false;
718}
719
720static inline void __da_handle_event_common(struct da_monitor *da_mon,
721 enum events event, da_id_type id)
722{
723 if (!da_event(da_mon, event, id))
724 da_monitor_reset(da_mon);
725}
726
727static inline void __da_handle_event(struct da_monitor *da_mon,
728 enum events event, da_id_type id)
729{
730 if (da_monitor_handling_event(da_mon))
731 __da_handle_event_common(da_mon, event, id);
732}
733
734static inline bool __da_handle_start_event(struct da_monitor *da_mon,
735 enum events event, da_id_type id)
736{
737 if (!da_monitor_enabled())
738 return 0;
739 if (unlikely(!da_monitoring(da_mon))) {
740 da_monitor_start(da_mon);
741 return 0;
742 }
743
744 __da_handle_event_common(da_mon, event, id);
745
746 return 1;
747}
748
749static inline bool __da_handle_start_run_event(struct da_monitor *da_mon,
750 enum events event, da_id_type id)
751{
752 if (!da_monitor_enabled())
753 return 0;
754 if (unlikely(!da_monitoring(da_mon)))
755 da_monitor_start(da_mon);
756
757 __da_handle_event_common(da_mon, event, id);
758
759 return 1;
760}
761
762#if RV_MON_TYPE == RV_MON_GLOBAL || RV_MON_TYPE == RV_MON_PER_CPU
763/*
764 * Handle event for implicit monitor: da_get_monitor() will figure out
765 * the monitor.
766 */
767
768/*
769 * da_handle_event - handle an event
770 */
771static inline void da_handle_event(enum events event)
772{
773 da_implicit_guard();
774 __da_handle_event(da_get_monitor(), event, 0);
775}
776
777/*
778 * da_handle_start_event - start monitoring or handle event
779 *
780 * This function is used to notify the monitor that the system is returning
781 * to the initial state, so the monitor can start monitoring in the next event.
782 * Thus:
783 *
784 * If the monitor already started, handle the event.
785 * If the monitor did not start yet, start the monitor but skip the event.
786 */
787static inline bool da_handle_start_event(enum events event)
788{
789 da_implicit_guard();
790 return __da_handle_start_event(da_get_monitor(), event, 0);
791}
792
793/*
794 * da_handle_start_run_event - start monitoring and handle event
795 *
796 * This function is used to notify the monitor that the system is in the
797 * initial state, so the monitor can start monitoring and handling event.
798 */
799static inline bool da_handle_start_run_event(enum events event)
800{
801 da_implicit_guard();
802 return __da_handle_start_run_event(da_get_monitor(), event, 0);
803}
804
805#elif RV_MON_TYPE == RV_MON_PER_TASK
806/*
807 * Handle event for per task.
808 */
809
810/*
811 * da_handle_event - handle an event
812 */
813static inline void da_handle_event(struct task_struct *tsk, enum events event)
814{
815 __da_handle_event(da_get_monitor(tsk), event, tsk->pid);
816}
817
818/*
819 * da_handle_start_event - start monitoring or handle event
820 *
821 * This function is used to notify the monitor that the system is returning
822 * to the initial state, so the monitor can start monitoring in the next event.
823 * Thus:
824 *
825 * If the monitor already started, handle the event.
826 * If the monitor did not start yet, start the monitor but skip the event.
827 */
828static inline bool da_handle_start_event(struct task_struct *tsk,
829 enum events event)
830{
831 return __da_handle_start_event(da_get_monitor(tsk), event, tsk->pid);
832}
833
834/*
835 * da_handle_start_run_event - start monitoring and handle event
836 *
837 * This function is used to notify the monitor that the system is in the
838 * initial state, so the monitor can start monitoring and handling event.
839 */
840static inline bool da_handle_start_run_event(struct task_struct *tsk,
841 enum events event)
842{
843 return __da_handle_start_run_event(da_get_monitor(tsk), event, tsk->pid);
844}
845
846#elif RV_MON_TYPE == RV_MON_PER_OBJ
847/*
848 * Handle event for per object.
849 */
850
851/*
852 * da_handle_event - handle an event
853 */
854static inline void da_handle_event(da_id_type id, monitor_target target, enum events event)
855{
856 struct da_monitor *da_mon;
857
858 guard(rcu)();
859 da_mon = da_get_monitor(id, target);
860 if (likely(da_mon))
861 __da_handle_event(da_mon, event, id);
862}
863
864/*
865 * da_handle_start_event - start monitoring or handle event
866 *
867 * This function is used to notify the monitor that the system is returning
868 * to the initial state, so the monitor can start monitoring in the next event.
869 * Thus:
870 *
871 * If the monitor already started, handle the event.
872 * If the monitor did not start yet, start the monitor but skip the event.
873 */
874static inline bool da_handle_start_event(da_id_type id, monitor_target target,
875 enum events event)
876{
877 struct da_monitor *da_mon;
878
879 guard(rcu)();
880 da_mon = da_get_monitor(id, target);
881 da_mon = da_prepare_storage(id, target, da_mon);
882 if (unlikely(!da_mon))
883 return 0;
884 return __da_handle_start_event(da_mon, event, id);
885}
886
887/*
888 * da_handle_start_run_event - start monitoring and handle event
889 *
890 * This function is used to notify the monitor that the system is in the
891 * initial state, so the monitor can start monitoring and handling event.
892 */
893static inline bool da_handle_start_run_event(da_id_type id, monitor_target target,
894 enum events event)
895{
896 struct da_monitor *da_mon;
897
898 guard(rcu)();
899 da_mon = da_get_monitor(id, target);
900 da_mon = da_prepare_storage(id, target, da_mon);
901 if (unlikely(!da_mon))
902 return 0;
903 return __da_handle_start_run_event(da_mon, event, id);
904}
905
906static inline void da_reset(da_id_type id, monitor_target target)
907{
908 struct da_monitor *da_mon;
909
910 guard(rcu)();
911 da_mon = da_get_monitor(id, target);
912 if (likely(da_mon))
913 da_monitor_reset(da_mon);
914}
915#endif /* RV_MON_TYPE */
916
917#if IS_ENABLED(CONFIG_RV_MONITORS_KUNIT_TEST)
918#if RV_MON_TYPE == RV_MON_PER_TASK
919#define RV_MON_OPS_INIT() { \
920 .rv_this = &rv_this, \
921 .is_per_task = true, \
922 .task_slot = &task_mon_slot, \
923 .task_reset = da_reset, \
924}
925#else
926#define RV_MON_OPS_INIT() { \
927 .rv_this = &rv_this, \
928 .monitor_init = da_monitor_init, \
929 .monitor_destroy = da_monitor_destroy, \
930}
931#endif /* RV_MON_TYPE */
932#endif /* CONFIG_RV_MONITORS_KUNIT_TEST */
933
934#endif