1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * trace helpers. 4 * 5 * Copyright (C) 2022 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org> 6 */ 7 8 #include <sys/sendfile.h> 9 #include <tracefs.h> 10 #include <signal.h> 11 #include <stdlib.h> 12 #include <unistd.h> 13 #include <errno.h> 14 15 #include <rv.h> 16 #include <trace.h> 17 #include <utils.h> 18 19 /* 20 * create_instance - create a trace instance with *instance_name 21 */ 22 static struct tracefs_instance *create_instance(char *instance_name) 23 { 24 return tracefs_instance_create(instance_name); 25 } 26 27 /* 28 * destroy_instance - remove a trace instance and free the data 29 */ 30 static void destroy_instance(struct tracefs_instance *inst) 31 { 32 tracefs_instance_destroy(inst); 33 tracefs_instance_free(inst); 34 } 35 36 /** 37 * collect_registered_events - call the existing callback function for the event 38 * 39 * If an event has a registered callback function, call it. 40 * Otherwise, ignore the event. 41 * 42 * Returns 0 if the event was collected, 1 if the tool should stop collecting trace. 43 */ 44 int 45 collect_registered_events(struct tep_event *event, struct tep_record *record, 46 int cpu, void *context) 47 { 48 struct trace_instance *trace = context; 49 struct trace_seq *s = trace->seq; 50 51 if (should_stop()) 52 return 1; 53 54 if (!event->handler) 55 return 0; 56 57 event->handler(s, record, event, context); 58 59 return 0; 60 } 61 62 /** 63 * trace_instance_destroy - destroy and free a rv trace instance 64 */ 65 void trace_instance_destroy(struct trace_instance *trace) 66 { 67 if (trace->inst) { 68 destroy_instance(trace->inst); 69 trace->inst = NULL; 70 } 71 72 if (trace->seq) { 73 free(trace->seq); 74 trace->seq = NULL; 75 } 76 77 if (trace->tep) { 78 tep_free(trace->tep); 79 trace->tep = NULL; 80 } 81 } 82 83 /** 84 * trace_instance_init - create an trace instance 85 * 86 * It is more than the tracefs instance, as it contains other 87 * things required for the tracing, such as the local events and 88 * a seq file. 89 * 90 * Note that the trace instance is returned disabled. This allows 91 * the tool to apply some other configs, like setting priority 92 * to the kernel threads, before starting generating trace entries. 93 * 94 * Returns 0 on success, non-zero otherwise. 95 */ 96 int trace_instance_init(struct trace_instance *trace, char *name) 97 { 98 trace->seq = calloc(1, sizeof(*trace->seq)); 99 if (!trace->seq) 100 goto out_err; 101 102 trace_seq_init(trace->seq); 103 104 trace->inst = create_instance(name); 105 if (!trace->inst) 106 goto out_err; 107 108 trace->tep = tracefs_local_events(NULL); 109 if (!trace->tep) 110 goto out_err; 111 112 /* 113 * Let the main enable the record after setting some other 114 * things such as the priority of the tracer's threads. 115 */ 116 tracefs_trace_off(trace->inst); 117 118 return 0; 119 120 out_err: 121 trace_instance_destroy(trace); 122 return 1; 123 } 124 125 /** 126 * trace_instance_start - start tracing a given rv instance 127 * 128 * Returns 0 on success, -1 otherwise. 129 */ 130 int trace_instance_start(struct trace_instance *trace) 131 { 132 return tracefs_trace_on(trace->inst); 133 } 134