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 */ 22static 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 */ 30static 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 */ 44int 45collect_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 */ 65void 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 */ 96int 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 120out_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 */ 130int trace_instance_start(struct trace_instance *trace) 131{ 132 return tracefs_trace_on(trace->inst); 133} 134