xref: /aosp_15_r20/external/blktrace/btt/proc.c (revision 1a3d31e37cc95e9919fd86900a2b6a555f55952c)
1*1a3d31e3SAndroid Build Coastguard Worker /*
2*1a3d31e3SAndroid Build Coastguard Worker  * blktrace output analysis: generate a timeline & gather statistics
3*1a3d31e3SAndroid Build Coastguard Worker  *
4*1a3d31e3SAndroid Build Coastguard Worker  * Copyright (C) 2006 Alan D. Brunelle <[email protected]>
5*1a3d31e3SAndroid Build Coastguard Worker  *
6*1a3d31e3SAndroid Build Coastguard Worker  *  This program is free software; you can redistribute it and/or modify
7*1a3d31e3SAndroid Build Coastguard Worker  *  it under the terms of the GNU General Public License as published by
8*1a3d31e3SAndroid Build Coastguard Worker  *  the Free Software Foundation; either version 2 of the License, or
9*1a3d31e3SAndroid Build Coastguard Worker  *  (at your option) any later version.
10*1a3d31e3SAndroid Build Coastguard Worker  *
11*1a3d31e3SAndroid Build Coastguard Worker  *  This program is distributed in the hope that it will be useful,
12*1a3d31e3SAndroid Build Coastguard Worker  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13*1a3d31e3SAndroid Build Coastguard Worker  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*1a3d31e3SAndroid Build Coastguard Worker  *  GNU General Public License for more details.
15*1a3d31e3SAndroid Build Coastguard Worker  *
16*1a3d31e3SAndroid Build Coastguard Worker  *  You should have received a copy of the GNU General Public License
17*1a3d31e3SAndroid Build Coastguard Worker  *  along with this program; if not, write to the Free Software
18*1a3d31e3SAndroid Build Coastguard Worker  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19*1a3d31e3SAndroid Build Coastguard Worker  *
20*1a3d31e3SAndroid Build Coastguard Worker  */
21*1a3d31e3SAndroid Build Coastguard Worker #include <string.h>
22*1a3d31e3SAndroid Build Coastguard Worker 
23*1a3d31e3SAndroid Build Coastguard Worker #include "globals.h"
24*1a3d31e3SAndroid Build Coastguard Worker 
25*1a3d31e3SAndroid Build Coastguard Worker struct pn_info {
26*1a3d31e3SAndroid Build Coastguard Worker 	struct rb_node rb_node;
27*1a3d31e3SAndroid Build Coastguard Worker 	struct p_info *pip;
28*1a3d31e3SAndroid Build Coastguard Worker 	union {
29*1a3d31e3SAndroid Build Coastguard Worker 		char *name;
30*1a3d31e3SAndroid Build Coastguard Worker 		__u32 pid;
31*1a3d31e3SAndroid Build Coastguard Worker 	}  u;
32*1a3d31e3SAndroid Build Coastguard Worker };
33*1a3d31e3SAndroid Build Coastguard Worker 
34*1a3d31e3SAndroid Build Coastguard Worker struct rb_root root_pid, root_name;
35*1a3d31e3SAndroid Build Coastguard Worker 
__foreach(struct rb_node * n,void (* f)(struct p_info *,void *),void * arg)36*1a3d31e3SAndroid Build Coastguard Worker static void __foreach(struct rb_node *n, void (*f)(struct p_info *, void *),
37*1a3d31e3SAndroid Build Coastguard Worker 			void *arg)
38*1a3d31e3SAndroid Build Coastguard Worker {
39*1a3d31e3SAndroid Build Coastguard Worker 	if (n) {
40*1a3d31e3SAndroid Build Coastguard Worker 		__foreach(n->rb_left, f, arg);
41*1a3d31e3SAndroid Build Coastguard Worker 		f(rb_entry(n, struct pn_info, rb_node)->pip, arg);
42*1a3d31e3SAndroid Build Coastguard Worker 		__foreach(n->rb_right, f, arg);
43*1a3d31e3SAndroid Build Coastguard Worker 	}
44*1a3d31e3SAndroid Build Coastguard Worker }
45*1a3d31e3SAndroid Build Coastguard Worker 
__destroy(struct rb_node * n,int free_name,int free_pip)46*1a3d31e3SAndroid Build Coastguard Worker static void __destroy(struct rb_node *n, int free_name, int free_pip)
47*1a3d31e3SAndroid Build Coastguard Worker {
48*1a3d31e3SAndroid Build Coastguard Worker 	if (n) {
49*1a3d31e3SAndroid Build Coastguard Worker 		struct pn_info *pnp = rb_entry(n, struct pn_info, rb_node);
50*1a3d31e3SAndroid Build Coastguard Worker 
51*1a3d31e3SAndroid Build Coastguard Worker 		__destroy(n->rb_left, free_name, free_pip);
52*1a3d31e3SAndroid Build Coastguard Worker 		__destroy(n->rb_right, free_name, free_pip);
53*1a3d31e3SAndroid Build Coastguard Worker 
54*1a3d31e3SAndroid Build Coastguard Worker 		if (free_name)
55*1a3d31e3SAndroid Build Coastguard Worker 			free(pnp->u.name);
56*1a3d31e3SAndroid Build Coastguard Worker 		if (free_pip) {
57*1a3d31e3SAndroid Build Coastguard Worker 			free(pnp->pip->name);
58*1a3d31e3SAndroid Build Coastguard Worker 			region_exit(&pnp->pip->regions);
59*1a3d31e3SAndroid Build Coastguard Worker 			free(pnp->pip);
60*1a3d31e3SAndroid Build Coastguard Worker 		}
61*1a3d31e3SAndroid Build Coastguard Worker 		free(pnp);
62*1a3d31e3SAndroid Build Coastguard Worker 	}
63*1a3d31e3SAndroid Build Coastguard Worker }
64*1a3d31e3SAndroid Build Coastguard Worker 
__find_process_pid(__u32 pid)65*1a3d31e3SAndroid Build Coastguard Worker struct p_info * __find_process_pid(__u32 pid)
66*1a3d31e3SAndroid Build Coastguard Worker {
67*1a3d31e3SAndroid Build Coastguard Worker 	struct pn_info *this;
68*1a3d31e3SAndroid Build Coastguard Worker 	struct rb_node *n = root_pid.rb_node;
69*1a3d31e3SAndroid Build Coastguard Worker 
70*1a3d31e3SAndroid Build Coastguard Worker 	while (n) {
71*1a3d31e3SAndroid Build Coastguard Worker 		this = rb_entry(n, struct pn_info, rb_node);
72*1a3d31e3SAndroid Build Coastguard Worker 		if (pid < this->u.pid)
73*1a3d31e3SAndroid Build Coastguard Worker 			n = n->rb_left;
74*1a3d31e3SAndroid Build Coastguard Worker 		else if (pid > this->u.pid)
75*1a3d31e3SAndroid Build Coastguard Worker 			n = n->rb_right;
76*1a3d31e3SAndroid Build Coastguard Worker 		else
77*1a3d31e3SAndroid Build Coastguard Worker 			return this->pip;
78*1a3d31e3SAndroid Build Coastguard Worker 	}
79*1a3d31e3SAndroid Build Coastguard Worker 
80*1a3d31e3SAndroid Build Coastguard Worker 	return NULL;
81*1a3d31e3SAndroid Build Coastguard Worker }
82*1a3d31e3SAndroid Build Coastguard Worker 
__find_process_name(char * name)83*1a3d31e3SAndroid Build Coastguard Worker struct p_info *__find_process_name(char *name)
84*1a3d31e3SAndroid Build Coastguard Worker {
85*1a3d31e3SAndroid Build Coastguard Worker 	int cmp;
86*1a3d31e3SAndroid Build Coastguard Worker 	struct pn_info *this;
87*1a3d31e3SAndroid Build Coastguard Worker 	struct rb_node *n = root_name.rb_node;
88*1a3d31e3SAndroid Build Coastguard Worker 
89*1a3d31e3SAndroid Build Coastguard Worker 	while (n) {
90*1a3d31e3SAndroid Build Coastguard Worker 		this = rb_entry(n, struct pn_info, rb_node);
91*1a3d31e3SAndroid Build Coastguard Worker 		cmp = strcmp(name, this->u.name);
92*1a3d31e3SAndroid Build Coastguard Worker 		if (cmp < 0)
93*1a3d31e3SAndroid Build Coastguard Worker 			n = n->rb_left;
94*1a3d31e3SAndroid Build Coastguard Worker 		else if (cmp > 0)
95*1a3d31e3SAndroid Build Coastguard Worker 			n = n->rb_right;
96*1a3d31e3SAndroid Build Coastguard Worker 		else
97*1a3d31e3SAndroid Build Coastguard Worker 			return this->pip;
98*1a3d31e3SAndroid Build Coastguard Worker 	}
99*1a3d31e3SAndroid Build Coastguard Worker 
100*1a3d31e3SAndroid Build Coastguard Worker 	return NULL;
101*1a3d31e3SAndroid Build Coastguard Worker }
102*1a3d31e3SAndroid Build Coastguard Worker 
insert_pid(struct p_info * that,__u32 pid)103*1a3d31e3SAndroid Build Coastguard Worker static void insert_pid(struct p_info *that, __u32 pid)
104*1a3d31e3SAndroid Build Coastguard Worker {
105*1a3d31e3SAndroid Build Coastguard Worker 	struct pn_info *this;
106*1a3d31e3SAndroid Build Coastguard Worker 	struct rb_node *parent = NULL;
107*1a3d31e3SAndroid Build Coastguard Worker 	struct rb_node **p = &root_pid.rb_node;
108*1a3d31e3SAndroid Build Coastguard Worker 
109*1a3d31e3SAndroid Build Coastguard Worker 	while (*p) {
110*1a3d31e3SAndroid Build Coastguard Worker 		parent = *p;
111*1a3d31e3SAndroid Build Coastguard Worker 		this = rb_entry(parent, struct pn_info, rb_node);
112*1a3d31e3SAndroid Build Coastguard Worker 
113*1a3d31e3SAndroid Build Coastguard Worker 		if (pid < this->u.pid)
114*1a3d31e3SAndroid Build Coastguard Worker 			p = &(*p)->rb_left;
115*1a3d31e3SAndroid Build Coastguard Worker 		else if (pid > this->u.pid)
116*1a3d31e3SAndroid Build Coastguard Worker 			p = &(*p)->rb_right;
117*1a3d31e3SAndroid Build Coastguard Worker 		else
118*1a3d31e3SAndroid Build Coastguard Worker 			return;	// Already there
119*1a3d31e3SAndroid Build Coastguard Worker 	}
120*1a3d31e3SAndroid Build Coastguard Worker 
121*1a3d31e3SAndroid Build Coastguard Worker 	this = malloc(sizeof(struct pn_info));
122*1a3d31e3SAndroid Build Coastguard Worker 	this->u.pid = pid;
123*1a3d31e3SAndroid Build Coastguard Worker 	this->pip = that;
124*1a3d31e3SAndroid Build Coastguard Worker 
125*1a3d31e3SAndroid Build Coastguard Worker 	rb_link_node(&this->rb_node, parent, p);
126*1a3d31e3SAndroid Build Coastguard Worker 	rb_insert_color(&this->rb_node, &root_pid);
127*1a3d31e3SAndroid Build Coastguard Worker }
128*1a3d31e3SAndroid Build Coastguard Worker 
insert_name(struct p_info * that)129*1a3d31e3SAndroid Build Coastguard Worker static void insert_name(struct p_info *that)
130*1a3d31e3SAndroid Build Coastguard Worker {
131*1a3d31e3SAndroid Build Coastguard Worker 	int cmp;
132*1a3d31e3SAndroid Build Coastguard Worker 	struct pn_info *this;
133*1a3d31e3SAndroid Build Coastguard Worker 	struct rb_node *parent = NULL;
134*1a3d31e3SAndroid Build Coastguard Worker 	struct rb_node **p = &root_name.rb_node;
135*1a3d31e3SAndroid Build Coastguard Worker 
136*1a3d31e3SAndroid Build Coastguard Worker 	while (*p) {
137*1a3d31e3SAndroid Build Coastguard Worker 		parent = *p;
138*1a3d31e3SAndroid Build Coastguard Worker 		this = rb_entry(parent, struct pn_info, rb_node);
139*1a3d31e3SAndroid Build Coastguard Worker 		cmp = strcmp(that->name, this->u.name);
140*1a3d31e3SAndroid Build Coastguard Worker 
141*1a3d31e3SAndroid Build Coastguard Worker 		if (cmp < 0)
142*1a3d31e3SAndroid Build Coastguard Worker 			p = &(*p)->rb_left;
143*1a3d31e3SAndroid Build Coastguard Worker 		else if (cmp > 0)
144*1a3d31e3SAndroid Build Coastguard Worker 			p = &(*p)->rb_right;
145*1a3d31e3SAndroid Build Coastguard Worker 		else
146*1a3d31e3SAndroid Build Coastguard Worker 			return;	// Already there...
147*1a3d31e3SAndroid Build Coastguard Worker 	}
148*1a3d31e3SAndroid Build Coastguard Worker 
149*1a3d31e3SAndroid Build Coastguard Worker 	this = malloc(sizeof(struct pn_info));
150*1a3d31e3SAndroid Build Coastguard Worker 	this->u.name = strdup(that->name);
151*1a3d31e3SAndroid Build Coastguard Worker 	this->pip = that;
152*1a3d31e3SAndroid Build Coastguard Worker 
153*1a3d31e3SAndroid Build Coastguard Worker 	rb_link_node(&this->rb_node, parent, p);
154*1a3d31e3SAndroid Build Coastguard Worker 	rb_insert_color(&this->rb_node, &root_name);
155*1a3d31e3SAndroid Build Coastguard Worker }
156*1a3d31e3SAndroid Build Coastguard Worker 
insert(struct p_info * pip)157*1a3d31e3SAndroid Build Coastguard Worker static void insert(struct p_info *pip)
158*1a3d31e3SAndroid Build Coastguard Worker {
159*1a3d31e3SAndroid Build Coastguard Worker 	insert_pid(pip, pip->pid);
160*1a3d31e3SAndroid Build Coastguard Worker 	insert_name(pip);
161*1a3d31e3SAndroid Build Coastguard Worker }
162*1a3d31e3SAndroid Build Coastguard Worker 
pip_alloc(void)163*1a3d31e3SAndroid Build Coastguard Worker static inline struct p_info *pip_alloc(void)
164*1a3d31e3SAndroid Build Coastguard Worker {
165*1a3d31e3SAndroid Build Coastguard Worker 	return memset(malloc(sizeof(struct p_info)), 0, sizeof(struct p_info));
166*1a3d31e3SAndroid Build Coastguard Worker }
167*1a3d31e3SAndroid Build Coastguard Worker 
find_process(__u32 pid,char * name)168*1a3d31e3SAndroid Build Coastguard Worker struct p_info *find_process(__u32 pid, char *name)
169*1a3d31e3SAndroid Build Coastguard Worker {
170*1a3d31e3SAndroid Build Coastguard Worker 	struct p_info *pip;
171*1a3d31e3SAndroid Build Coastguard Worker 
172*1a3d31e3SAndroid Build Coastguard Worker 	if (pid != ((__u32)-1)) {
173*1a3d31e3SAndroid Build Coastguard Worker 		if ((pip = __find_process_pid(pid)) != NULL)
174*1a3d31e3SAndroid Build Coastguard Worker 			return pip;
175*1a3d31e3SAndroid Build Coastguard Worker 		else if (name) {
176*1a3d31e3SAndroid Build Coastguard Worker 			pip = __find_process_name(name);
177*1a3d31e3SAndroid Build Coastguard Worker 
178*1a3d31e3SAndroid Build Coastguard Worker 			if (pip && pid != pip->pid) {
179*1a3d31e3SAndroid Build Coastguard Worker 				/*
180*1a3d31e3SAndroid Build Coastguard Worker 				 * This is a process with the same name
181*1a3d31e3SAndroid Build Coastguard Worker 				 * as another, but a different PID.
182*1a3d31e3SAndroid Build Coastguard Worker 				 *
183*1a3d31e3SAndroid Build Coastguard Worker 				 * We'll store a reference in the PID
184*1a3d31e3SAndroid Build Coastguard Worker 				 * tree...
185*1a3d31e3SAndroid Build Coastguard Worker 				 */
186*1a3d31e3SAndroid Build Coastguard Worker 				insert_pid(pip, pid);
187*1a3d31e3SAndroid Build Coastguard Worker 			}
188*1a3d31e3SAndroid Build Coastguard Worker 			return pip;
189*1a3d31e3SAndroid Build Coastguard Worker 		}
190*1a3d31e3SAndroid Build Coastguard Worker 
191*1a3d31e3SAndroid Build Coastguard Worker 		/*
192*1a3d31e3SAndroid Build Coastguard Worker 		 * We're here because we have a pid, and no name, but
193*1a3d31e3SAndroid Build Coastguard Worker 		 * we didn't find a process ...
194*1a3d31e3SAndroid Build Coastguard Worker 		 *
195*1a3d31e3SAndroid Build Coastguard Worker 		 * We'll craft one using the pid...
196*1a3d31e3SAndroid Build Coastguard Worker 		 */
197*1a3d31e3SAndroid Build Coastguard Worker 
198*1a3d31e3SAndroid Build Coastguard Worker 		name = alloca(256);
199*1a3d31e3SAndroid Build Coastguard Worker 		sprintf(name, "pid%09u", pid);
200*1a3d31e3SAndroid Build Coastguard Worker 		process_alloc(pid, name);
201*1a3d31e3SAndroid Build Coastguard Worker 		return __find_process_pid(pid);
202*1a3d31e3SAndroid Build Coastguard Worker 	}
203*1a3d31e3SAndroid Build Coastguard Worker 
204*1a3d31e3SAndroid Build Coastguard Worker 	return __find_process_name(name);
205*1a3d31e3SAndroid Build Coastguard Worker }
206*1a3d31e3SAndroid Build Coastguard Worker 
process_alloc(__u32 pid,char * name)207*1a3d31e3SAndroid Build Coastguard Worker void process_alloc(__u32 pid, char *name)
208*1a3d31e3SAndroid Build Coastguard Worker {
209*1a3d31e3SAndroid Build Coastguard Worker 	struct p_info *pip = find_process(pid, name);
210*1a3d31e3SAndroid Build Coastguard Worker 
211*1a3d31e3SAndroid Build Coastguard Worker 	if (pip == NULL) {
212*1a3d31e3SAndroid Build Coastguard Worker 		pip = pip_alloc();
213*1a3d31e3SAndroid Build Coastguard Worker 		pip->pid = pid;
214*1a3d31e3SAndroid Build Coastguard Worker 		region_init(&pip->regions);
215*1a3d31e3SAndroid Build Coastguard Worker 		pip->last_q = (__u64)-1;
216*1a3d31e3SAndroid Build Coastguard Worker 		pip->name = strdup(name);
217*1a3d31e3SAndroid Build Coastguard Worker 
218*1a3d31e3SAndroid Build Coastguard Worker 		insert(pip);
219*1a3d31e3SAndroid Build Coastguard Worker 	}
220*1a3d31e3SAndroid Build Coastguard Worker }
221*1a3d31e3SAndroid Build Coastguard Worker 
pip_update_q(struct io * iop)222*1a3d31e3SAndroid Build Coastguard Worker void pip_update_q(struct io *iop)
223*1a3d31e3SAndroid Build Coastguard Worker {
224*1a3d31e3SAndroid Build Coastguard Worker 	if (iop->pip) {
225*1a3d31e3SAndroid Build Coastguard Worker 		if (remapper_dev(iop->dip->device))
226*1a3d31e3SAndroid Build Coastguard Worker 			update_lq(&iop->pip->last_q, &iop->pip->avgs.q2q_dm,
227*1a3d31e3SAndroid Build Coastguard Worker 								iop->t.time);
228*1a3d31e3SAndroid Build Coastguard Worker 		else
229*1a3d31e3SAndroid Build Coastguard Worker 			update_lq(&iop->pip->last_q, &iop->pip->avgs.q2q,
230*1a3d31e3SAndroid Build Coastguard Worker 								iop->t.time);
231*1a3d31e3SAndroid Build Coastguard Worker 		update_qregion(&iop->pip->regions, iop->t.time);
232*1a3d31e3SAndroid Build Coastguard Worker 	}
233*1a3d31e3SAndroid Build Coastguard Worker }
234*1a3d31e3SAndroid Build Coastguard Worker 
pip_foreach_out(void (* f)(struct p_info *,void *),void * arg)235*1a3d31e3SAndroid Build Coastguard Worker void pip_foreach_out(void (*f)(struct p_info *, void *), void *arg)
236*1a3d31e3SAndroid Build Coastguard Worker {
237*1a3d31e3SAndroid Build Coastguard Worker 	if (exes == NULL)
238*1a3d31e3SAndroid Build Coastguard Worker 		__foreach(root_name.rb_node, f, arg);
239*1a3d31e3SAndroid Build Coastguard Worker 	else {
240*1a3d31e3SAndroid Build Coastguard Worker 		struct p_info *pip;
241*1a3d31e3SAndroid Build Coastguard Worker 		char *exe, *next, *exes_save = strdup(exes);
242*1a3d31e3SAndroid Build Coastguard Worker 
243*1a3d31e3SAndroid Build Coastguard Worker 		while (exes_save != NULL) {
244*1a3d31e3SAndroid Build Coastguard Worker 			exe = exes_save;
245*1a3d31e3SAndroid Build Coastguard Worker 			if ((next = strchr(exes_save, ',')) != NULL) {
246*1a3d31e3SAndroid Build Coastguard Worker 				*next = '\0';
247*1a3d31e3SAndroid Build Coastguard Worker 				exes_save = next+1;
248*1a3d31e3SAndroid Build Coastguard Worker 			} else
249*1a3d31e3SAndroid Build Coastguard Worker 				exes_save = NULL;
250*1a3d31e3SAndroid Build Coastguard Worker 
251*1a3d31e3SAndroid Build Coastguard Worker 			pip = __find_process_name(exe);
252*1a3d31e3SAndroid Build Coastguard Worker 			if (pip)
253*1a3d31e3SAndroid Build Coastguard Worker 				f(pip, arg);
254*1a3d31e3SAndroid Build Coastguard Worker 		}
255*1a3d31e3SAndroid Build Coastguard Worker 	}
256*1a3d31e3SAndroid Build Coastguard Worker }
257*1a3d31e3SAndroid Build Coastguard Worker 
pip_exit(void)258*1a3d31e3SAndroid Build Coastguard Worker void pip_exit(void)
259*1a3d31e3SAndroid Build Coastguard Worker {
260*1a3d31e3SAndroid Build Coastguard Worker 	__destroy(root_pid.rb_node, 0, 0);
261*1a3d31e3SAndroid Build Coastguard Worker 	__destroy(root_name.rb_node, 1, 1);
262*1a3d31e3SAndroid Build Coastguard Worker }
263