1Deterministic Automata Instrumentation 2====================================== 3 4The RV monitor file created by dot2k, with the name "$MODEL_NAME.c" 5includes a section dedicated to instrumentation. 6 7In the example of the wip.dot monitor created on [1], it will look like:: 8 9 /* 10 * This is the instrumentation part of the monitor. 11 * 12 * This is the section where manual work is required. Here the kernel events 13 * are translated into model's event. 14 * 15 */ 16 static void handle_preempt_disable(void *data, /* XXX: fill header */) 17 { 18 da_handle_event_wip(preempt_disable_wip); 19 } 20 21 static void handle_preempt_enable(void *data, /* XXX: fill header */) 22 { 23 da_handle_event_wip(preempt_enable_wip); 24 } 25 26 static void handle_sched_waking(void *data, /* XXX: fill header */) 27 { 28 da_handle_event_wip(sched_waking_wip); 29 } 30 31 static int enable_wip(void) 32 { 33 int retval; 34 35 retval = da_monitor_init_wip(); 36 if (retval) 37 return retval; 38 39 rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_preempt_disable); 40 rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_preempt_enable); 41 rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_sched_waking); 42 43 return 0; 44 } 45 46The comment at the top of the section explains the general idea: the 47instrumentation section translates *kernel events* into the *model's 48event*. 49 50Tracing callback functions 51-------------------------- 52 53The first three functions are the starting point of the callback *handler 54functions* for each of the three events from the wip model. The developer 55does not necessarily need to use them: they are just starting points. 56 57Using the example of:: 58 59 void handle_preempt_disable(void *data, /* XXX: fill header */) 60 { 61 da_handle_event_wip(preempt_disable_wip); 62 } 63 64The preempt_disable event from the model connects directly to the 65preemptirq:preempt_disable. The preemptirq:preempt_disable event 66has the following signature, from include/trace/events/preemptirq.h:: 67 68 TP_PROTO(unsigned long ip, unsigned long parent_ip) 69 70Hence, the handle_preempt_disable() function will look like:: 71 72 void handle_preempt_disable(void *data, unsigned long ip, unsigned long parent_ip) 73 74In this case, the kernel event translates one to one with the automata 75event, and indeed, no other change is required for this function. 76 77The next handler function, handle_preempt_enable() has the same argument 78list from the handle_preempt_disable(). The difference is that the 79preempt_enable event will be used to synchronize the system to the model. 80 81Initially, the *model* is placed in the initial state. However, the *system* 82might or might not be in the initial state. The monitor cannot start 83processing events until it knows that the system has reached the initial state. 84Otherwise, the monitor and the system could be out-of-sync. 85 86Looking at the automata definition, it is possible to see that the system 87and the model are expected to return to the initial state after the 88preempt_enable execution. Hence, it can be used to synchronize the 89system and the model at the initialization of the monitoring section. 90 91The start is informed via a special handle function, the 92"da_handle_start_event_$(MONITOR_NAME)(event)", in this case:: 93 94 da_handle_start_event_wip(preempt_enable_wip); 95 96So, the callback function will look like:: 97 98 void handle_preempt_enable(void *data, unsigned long ip, unsigned long parent_ip) 99 { 100 da_handle_start_event_wip(preempt_enable_wip); 101 } 102 103Finally, the "handle_sched_waking()" will look like:: 104 105 void handle_sched_waking(void *data, struct task_struct *task) 106 { 107 da_handle_event_wip(sched_waking_wip); 108 } 109 110And the explanation is left for the reader as an exercise. 111 112enable and disable functions 113---------------------------- 114 115dot2k automatically creates two special functions:: 116 117 enable_$(MONITOR_NAME)() 118 disable_$(MONITOR_NAME)() 119 120These functions are called when the monitor is enabled and disabled, 121respectively. 122 123They should be used to *attach* and *detach* the instrumentation to the running 124system. The developer must add to the relative function all that is needed to 125*attach* and *detach* its monitor to the system. 126 127For the wip case, these functions were named:: 128 129 enable_wip() 130 disable_wip() 131 132But no change was required because: by default, these functions *attach* and 133*detach* the tracepoints_to_attach, which was enough for this case. 134 135Instrumentation helpers 136----------------------- 137 138To complete the instrumentation, the *handler functions* need to be attached to a 139kernel event, at the monitoring enable phase. 140 141The RV interface also facilitates this step. For example, the macro "rv_attach_trace_probe()" 142is used to connect the wip model events to the relative kernel event. dot2k automatically 143adds "rv_attach_trace_probe()" function call for each model event in the enable phase, as 144a suggestion. 145 146For example, from the wip sample model:: 147 148 static int enable_wip(void) 149 { 150 int retval; 151 152 retval = da_monitor_init_wip(); 153 if (retval) 154 return retval; 155 156 rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_preempt_enable); 157 rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_sched_waking); 158 rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_preempt_disable); 159 160 return 0; 161 } 162 163The probes then need to be detached at the disable phase. 164 165[1] The wip model is presented in:: 166 167 Documentation/trace/rv/deterministic_automata.rst 168 169The wip monitor is presented in:: 170 171 Documentation/trace/rv/da_monitor_synthesis.rst 172