xref: /aosp_15_r20/external/trace-cmd/tracecmd/trace-stream.c (revision 58e6ee5f017f6a8912852c892d18457e4bafb554)
1*58e6ee5fSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*58e6ee5fSAndroid Build Coastguard Worker /*
3*58e6ee5fSAndroid Build Coastguard Worker  * Copyright (C) 2014 Red Hat Inc, Steven Rostedt <[email protected]>
4*58e6ee5fSAndroid Build Coastguard Worker  *
5*58e6ee5fSAndroid Build Coastguard Worker  */
6*58e6ee5fSAndroid Build Coastguard Worker #include <stdio.h>
7*58e6ee5fSAndroid Build Coastguard Worker #include <unistd.h>
8*58e6ee5fSAndroid Build Coastguard Worker #include <fcntl.h>
9*58e6ee5fSAndroid Build Coastguard Worker #include <errno.h>
10*58e6ee5fSAndroid Build Coastguard Worker 
11*58e6ee5fSAndroid Build Coastguard Worker #include <sys/time.h>
12*58e6ee5fSAndroid Build Coastguard Worker #include <sys/types.h>
13*58e6ee5fSAndroid Build Coastguard Worker 
14*58e6ee5fSAndroid Build Coastguard Worker #include "trace-local.h"
15*58e6ee5fSAndroid Build Coastguard Worker 
16*58e6ee5fSAndroid Build Coastguard Worker /*
17*58e6ee5fSAndroid Build Coastguard Worker  * Stream runs for a single machine. We are going to cheat
18*58e6ee5fSAndroid Build Coastguard Worker  * and use the trace-output and trace-input code to create
19*58e6ee5fSAndroid Build Coastguard Worker  * our pevent. First just create a trace.dat file and then read
20*58e6ee5fSAndroid Build Coastguard Worker  * it to create the pevent and handle.
21*58e6ee5fSAndroid Build Coastguard Worker  */
22*58e6ee5fSAndroid Build Coastguard Worker struct tracecmd_input *
trace_stream_init(struct buffer_instance * instance,int cpu,int fd,int cpus,struct hook_list * hooks,tracecmd_handle_init_func handle_init,int global)23*58e6ee5fSAndroid Build Coastguard Worker trace_stream_init(struct buffer_instance *instance, int cpu, int fd, int cpus,
24*58e6ee5fSAndroid Build Coastguard Worker 		  struct hook_list *hooks,
25*58e6ee5fSAndroid Build Coastguard Worker 		  tracecmd_handle_init_func handle_init, int global)
26*58e6ee5fSAndroid Build Coastguard Worker {
27*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_input *trace_input;
28*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_output *trace_output;
29*58e6ee5fSAndroid Build Coastguard Worker 	static FILE *fp = NULL;
30*58e6ee5fSAndroid Build Coastguard Worker 	static int tfd;
31*58e6ee5fSAndroid Build Coastguard Worker 	static int ofd;
32*58e6ee5fSAndroid Build Coastguard Worker 	long flags;
33*58e6ee5fSAndroid Build Coastguard Worker 
34*58e6ee5fSAndroid Build Coastguard Worker 	if (instance->handle) {
35*58e6ee5fSAndroid Build Coastguard Worker 		trace_input = instance->handle;
36*58e6ee5fSAndroid Build Coastguard Worker 		goto make_pipe;
37*58e6ee5fSAndroid Build Coastguard Worker 	}
38*58e6ee5fSAndroid Build Coastguard Worker 
39*58e6ee5fSAndroid Build Coastguard Worker 	if (!fp) {
40*58e6ee5fSAndroid Build Coastguard Worker 		fp = tmpfile();
41*58e6ee5fSAndroid Build Coastguard Worker 		if (!fp)
42*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
43*58e6ee5fSAndroid Build Coastguard Worker 		tfd = fileno(fp);
44*58e6ee5fSAndroid Build Coastguard Worker 
45*58e6ee5fSAndroid Build Coastguard Worker 		ofd = dup(tfd);
46*58e6ee5fSAndroid Build Coastguard Worker 		trace_output = tracecmd_output_create_fd(ofd);
47*58e6ee5fSAndroid Build Coastguard Worker 		if (!trace_output) {
48*58e6ee5fSAndroid Build Coastguard Worker 			fclose(fp);
49*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
50*58e6ee5fSAndroid Build Coastguard Worker 		}
51*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_output_write_headers(trace_output, NULL);
52*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_output_free(trace_output);
53*58e6ee5fSAndroid Build Coastguard Worker 	}
54*58e6ee5fSAndroid Build Coastguard Worker 
55*58e6ee5fSAndroid Build Coastguard Worker 	lseek(ofd, 0, SEEK_SET);
56*58e6ee5fSAndroid Build Coastguard Worker 
57*58e6ee5fSAndroid Build Coastguard Worker 	trace_input = tracecmd_alloc_fd(ofd, 0);
58*58e6ee5fSAndroid Build Coastguard Worker 	if (!trace_input) {
59*58e6ee5fSAndroid Build Coastguard Worker 		close(ofd);
60*58e6ee5fSAndroid Build Coastguard Worker 		goto fail;
61*58e6ee5fSAndroid Build Coastguard Worker 	}
62*58e6ee5fSAndroid Build Coastguard Worker 
63*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_read_headers(trace_input, TRACECMD_FILE_PRINTK) < 0)
64*58e6ee5fSAndroid Build Coastguard Worker 		goto fail_free_input;
65*58e6ee5fSAndroid Build Coastguard Worker 
66*58e6ee5fSAndroid Build Coastguard Worker 	if (handle_init)
67*58e6ee5fSAndroid Build Coastguard Worker 		handle_init(trace_input, hooks, global);
68*58e6ee5fSAndroid Build Coastguard Worker 
69*58e6ee5fSAndroid Build Coastguard Worker  make_pipe:
70*58e6ee5fSAndroid Build Coastguard Worker 	/* Do not block on this pipe */
71*58e6ee5fSAndroid Build Coastguard Worker 	flags = fcntl(fd, F_GETFL);
72*58e6ee5fSAndroid Build Coastguard Worker 	fcntl(fd, F_SETFL, flags | O_NONBLOCK);
73*58e6ee5fSAndroid Build Coastguard Worker 
74*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_make_pipe(trace_input, cpu, fd, cpus) < 0)
75*58e6ee5fSAndroid Build Coastguard Worker 		goto fail_free_input;
76*58e6ee5fSAndroid Build Coastguard Worker 
77*58e6ee5fSAndroid Build Coastguard Worker 	instance->handle = trace_input;
78*58e6ee5fSAndroid Build Coastguard Worker 
79*58e6ee5fSAndroid Build Coastguard Worker 	return trace_input;
80*58e6ee5fSAndroid Build Coastguard Worker 
81*58e6ee5fSAndroid Build Coastguard Worker  fail_free_input:
82*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_close(trace_input);
83*58e6ee5fSAndroid Build Coastguard Worker  fail:
84*58e6ee5fSAndroid Build Coastguard Worker 	fclose(fp);
85*58e6ee5fSAndroid Build Coastguard Worker 
86*58e6ee5fSAndroid Build Coastguard Worker 	return NULL;
87*58e6ee5fSAndroid Build Coastguard Worker }
88*58e6ee5fSAndroid Build Coastguard Worker 
trace_stream_read(struct pid_record_data * pids,int nr_pids,struct timeval * tv)89*58e6ee5fSAndroid Build Coastguard Worker int trace_stream_read(struct pid_record_data *pids, int nr_pids, struct timeval *tv)
90*58e6ee5fSAndroid Build Coastguard Worker {
91*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record *record;
92*58e6ee5fSAndroid Build Coastguard Worker 	struct pid_record_data *pid;
93*58e6ee5fSAndroid Build Coastguard Worker 	struct pid_record_data *last_pid;
94*58e6ee5fSAndroid Build Coastguard Worker 	fd_set rfds;
95*58e6ee5fSAndroid Build Coastguard Worker 	int top_rfd = 0;
96*58e6ee5fSAndroid Build Coastguard Worker 	int nr_fd;
97*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
98*58e6ee5fSAndroid Build Coastguard Worker 	int i;
99*58e6ee5fSAndroid Build Coastguard Worker 
100*58e6ee5fSAndroid Build Coastguard Worker 	last_pid = NULL;
101*58e6ee5fSAndroid Build Coastguard Worker 
102*58e6ee5fSAndroid Build Coastguard Worker  again:
103*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr_pids; i++) {
104*58e6ee5fSAndroid Build Coastguard Worker 		pid = &pids[i];
105*58e6ee5fSAndroid Build Coastguard Worker 
106*58e6ee5fSAndroid Build Coastguard Worker 		if (!pid->record)
107*58e6ee5fSAndroid Build Coastguard Worker 			pid->record = tracecmd_read_data(pid->instance->handle, pid->cpu);
108*58e6ee5fSAndroid Build Coastguard Worker 		record = pid->record;
109*58e6ee5fSAndroid Build Coastguard Worker 		if (!record && errno == EINVAL)
110*58e6ee5fSAndroid Build Coastguard Worker 			/* pipe has closed */
111*58e6ee5fSAndroid Build Coastguard Worker 			pid->closed = 1;
112*58e6ee5fSAndroid Build Coastguard Worker 
113*58e6ee5fSAndroid Build Coastguard Worker 		if (record &&
114*58e6ee5fSAndroid Build Coastguard Worker 		    (!last_pid || record->ts < last_pid->record->ts))
115*58e6ee5fSAndroid Build Coastguard Worker 			last_pid = pid;
116*58e6ee5fSAndroid Build Coastguard Worker 	}
117*58e6ee5fSAndroid Build Coastguard Worker 	if (last_pid) {
118*58e6ee5fSAndroid Build Coastguard Worker 		trace_show_data(last_pid->instance->handle, last_pid->record);
119*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_free_record(last_pid->record);
120*58e6ee5fSAndroid Build Coastguard Worker 		last_pid->record = NULL;
121*58e6ee5fSAndroid Build Coastguard Worker 		return 1;
122*58e6ee5fSAndroid Build Coastguard Worker 	}
123*58e6ee5fSAndroid Build Coastguard Worker 
124*58e6ee5fSAndroid Build Coastguard Worker 	nr_fd = 0;
125*58e6ee5fSAndroid Build Coastguard Worker 	FD_ZERO(&rfds);
126*58e6ee5fSAndroid Build Coastguard Worker 
127*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr_pids; i++) {
128*58e6ee5fSAndroid Build Coastguard Worker 		/* Do not process closed pipes */
129*58e6ee5fSAndroid Build Coastguard Worker 		if (pids[i].closed)
130*58e6ee5fSAndroid Build Coastguard Worker 			continue;
131*58e6ee5fSAndroid Build Coastguard Worker 		nr_fd++;
132*58e6ee5fSAndroid Build Coastguard Worker 		if (pids[i].brass[0] > top_rfd)
133*58e6ee5fSAndroid Build Coastguard Worker 			top_rfd = pids[i].brass[0];
134*58e6ee5fSAndroid Build Coastguard Worker 
135*58e6ee5fSAndroid Build Coastguard Worker 		FD_SET(pids[i].brass[0], &rfds);
136*58e6ee5fSAndroid Build Coastguard Worker 	}
137*58e6ee5fSAndroid Build Coastguard Worker 
138*58e6ee5fSAndroid Build Coastguard Worker 	if (!nr_fd)
139*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
140*58e6ee5fSAndroid Build Coastguard Worker 
141*58e6ee5fSAndroid Build Coastguard Worker 	ret = select(top_rfd + 1, &rfds, NULL, NULL, tv);
142*58e6ee5fSAndroid Build Coastguard Worker 
143*58e6ee5fSAndroid Build Coastguard Worker 	if (ret > 0)
144*58e6ee5fSAndroid Build Coastguard Worker 		goto again;
145*58e6ee5fSAndroid Build Coastguard Worker 
146*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
147*58e6ee5fSAndroid Build Coastguard Worker }
148