xref: /aosp_15_r20/external/blktrace/btt/p_live.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  * (C) Copyright 2009 Hewlett-Packard Development Company, L.P.
5*1a3d31e3SAndroid Build Coastguard Worker  *	Alan D. Brunelle ([email protected])
6*1a3d31e3SAndroid Build Coastguard Worker  *
7*1a3d31e3SAndroid Build Coastguard Worker  *  This program is free software; you can redistribute it and/or modify
8*1a3d31e3SAndroid Build Coastguard Worker  *  it under the terms of the GNU General Public License as published by
9*1a3d31e3SAndroid Build Coastguard Worker  *  the Free Software Foundation; either version 2 of the License, or
10*1a3d31e3SAndroid Build Coastguard Worker  *  (at your option) any later version.
11*1a3d31e3SAndroid Build Coastguard Worker  *
12*1a3d31e3SAndroid Build Coastguard Worker  *  This program is distributed in the hope that it will be useful,
13*1a3d31e3SAndroid Build Coastguard Worker  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14*1a3d31e3SAndroid Build Coastguard Worker  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*1a3d31e3SAndroid Build Coastguard Worker  *  GNU General Public License for more details.
16*1a3d31e3SAndroid Build Coastguard Worker  *
17*1a3d31e3SAndroid Build Coastguard Worker  *  You should have received a copy of the GNU General Public License
18*1a3d31e3SAndroid Build Coastguard Worker  *  along with this program; if not, write to the Free Software
19*1a3d31e3SAndroid Build Coastguard Worker  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20*1a3d31e3SAndroid Build Coastguard Worker  *
21*1a3d31e3SAndroid Build Coastguard Worker  */
22*1a3d31e3SAndroid Build Coastguard Worker #include "globals.h"
23*1a3d31e3SAndroid Build Coastguard Worker 
24*1a3d31e3SAndroid Build Coastguard Worker struct p_live {
25*1a3d31e3SAndroid Build Coastguard Worker 	struct rb_node rb_node;
26*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head head;
27*1a3d31e3SAndroid Build Coastguard Worker 	__u64 dt, ct;
28*1a3d31e3SAndroid Build Coastguard Worker };
29*1a3d31e3SAndroid Build Coastguard Worker 
30*1a3d31e3SAndroid Build Coastguard Worker struct get_info {
31*1a3d31e3SAndroid Build Coastguard Worker 	struct p_live_info *plip;
32*1a3d31e3SAndroid Build Coastguard Worker 	__u64 t_start, t_end;
33*1a3d31e3SAndroid Build Coastguard Worker 	__u64 tot_live;
34*1a3d31e3SAndroid Build Coastguard Worker 
35*1a3d31e3SAndroid Build Coastguard Worker 	FILE *ofp;
36*1a3d31e3SAndroid Build Coastguard Worker 	double last_0;
37*1a3d31e3SAndroid Build Coastguard Worker 	int base_y;
38*1a3d31e3SAndroid Build Coastguard Worker };
39*1a3d31e3SAndroid Build Coastguard Worker 
40*1a3d31e3SAndroid Build Coastguard Worker static struct rb_root p_live_root;
41*1a3d31e3SAndroid Build Coastguard Worker static LIST_HEAD(all_p_lives);
42*1a3d31e3SAndroid Build Coastguard Worker 
do_open(struct d_info * dip)43*1a3d31e3SAndroid Build Coastguard Worker static FILE *do_open(struct d_info *dip)
44*1a3d31e3SAndroid Build Coastguard Worker {
45*1a3d31e3SAndroid Build Coastguard Worker 	FILE *ofp;
46*1a3d31e3SAndroid Build Coastguard Worker 
47*1a3d31e3SAndroid Build Coastguard Worker 	if (do_p_live) {
48*1a3d31e3SAndroid Build Coastguard Worker 		char *bn = dip ? dip->dip_name : "sys";
49*1a3d31e3SAndroid Build Coastguard Worker 		char *nm = malloc(strlen(bn) + 16);
50*1a3d31e3SAndroid Build Coastguard Worker 
51*1a3d31e3SAndroid Build Coastguard Worker 		sprintf(nm, "%s_live.dat", bn);
52*1a3d31e3SAndroid Build Coastguard Worker 		ofp = my_fopen(nm, "w");
53*1a3d31e3SAndroid Build Coastguard Worker 		if (ofp)
54*1a3d31e3SAndroid Build Coastguard Worker 			add_file(ofp, nm);
55*1a3d31e3SAndroid Build Coastguard Worker 		else
56*1a3d31e3SAndroid Build Coastguard Worker 			free(nm);
57*1a3d31e3SAndroid Build Coastguard Worker 	}
58*1a3d31e3SAndroid Build Coastguard Worker 	else
59*1a3d31e3SAndroid Build Coastguard Worker 		ofp = NULL;
60*1a3d31e3SAndroid Build Coastguard Worker 
61*1a3d31e3SAndroid Build Coastguard Worker 	return ofp;
62*1a3d31e3SAndroid Build Coastguard Worker }
63*1a3d31e3SAndroid Build Coastguard Worker 
inside(struct p_live * plp,__u64 dt,__u64 ct)64*1a3d31e3SAndroid Build Coastguard Worker static inline int inside(struct p_live *plp, __u64 dt, __u64 ct)
65*1a3d31e3SAndroid Build Coastguard Worker {
66*1a3d31e3SAndroid Build Coastguard Worker 	if (plp->dt <= dt && dt <= plp->ct)
67*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
68*1a3d31e3SAndroid Build Coastguard Worker 	if (plp->dt <= ct && ct <= plp->ct)
69*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
70*1a3d31e3SAndroid Build Coastguard Worker 	if (dt < plp->dt && plp->ct < ct)
71*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
72*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
73*1a3d31e3SAndroid Build Coastguard Worker }
74*1a3d31e3SAndroid Build Coastguard Worker 
__p_live_add(struct rb_root * root,__u64 dt,__u64 ct)75*1a3d31e3SAndroid Build Coastguard Worker static void __p_live_add(struct rb_root *root, __u64 dt, __u64 ct)
76*1a3d31e3SAndroid Build Coastguard Worker {
77*1a3d31e3SAndroid Build Coastguard Worker 	struct p_live *plp;
78*1a3d31e3SAndroid Build Coastguard Worker 	struct rb_node *parent = NULL;
79*1a3d31e3SAndroid Build Coastguard Worker 	struct rb_node **p = &root->rb_node;
80*1a3d31e3SAndroid Build Coastguard Worker 
81*1a3d31e3SAndroid Build Coastguard Worker 	while (*p) {
82*1a3d31e3SAndroid Build Coastguard Worker 		parent = *p;
83*1a3d31e3SAndroid Build Coastguard Worker 		plp = rb_entry(parent, struct p_live, rb_node);
84*1a3d31e3SAndroid Build Coastguard Worker 
85*1a3d31e3SAndroid Build Coastguard Worker 		if (inside(plp, dt, ct)) {
86*1a3d31e3SAndroid Build Coastguard Worker 			list_del(&plp->head);
87*1a3d31e3SAndroid Build Coastguard Worker 			rb_erase(&plp->rb_node, root);
88*1a3d31e3SAndroid Build Coastguard Worker 			__p_live_add(root, min(plp->dt, dt), max(plp->ct, ct));
89*1a3d31e3SAndroid Build Coastguard Worker 			free(plp);
90*1a3d31e3SAndroid Build Coastguard Worker 			return;
91*1a3d31e3SAndroid Build Coastguard Worker 		}
92*1a3d31e3SAndroid Build Coastguard Worker 
93*1a3d31e3SAndroid Build Coastguard Worker 		if (ct < plp->dt)
94*1a3d31e3SAndroid Build Coastguard Worker 			p = &(*p)->rb_left;
95*1a3d31e3SAndroid Build Coastguard Worker 		else
96*1a3d31e3SAndroid Build Coastguard Worker 			p = &(*p)->rb_right;
97*1a3d31e3SAndroid Build Coastguard Worker 	}
98*1a3d31e3SAndroid Build Coastguard Worker 
99*1a3d31e3SAndroid Build Coastguard Worker 	plp = malloc(sizeof(*plp));
100*1a3d31e3SAndroid Build Coastguard Worker 	plp->dt = dt;
101*1a3d31e3SAndroid Build Coastguard Worker 	plp->ct = ct;
102*1a3d31e3SAndroid Build Coastguard Worker 
103*1a3d31e3SAndroid Build Coastguard Worker 	rb_link_node(&plp->rb_node, parent, p);
104*1a3d31e3SAndroid Build Coastguard Worker 	rb_insert_color(&plp->rb_node, root);
105*1a3d31e3SAndroid Build Coastguard Worker 	list_add_tail(&plp->head, &all_p_lives);
106*1a3d31e3SAndroid Build Coastguard Worker }
107*1a3d31e3SAndroid Build Coastguard Worker 
p_live_alloc(void)108*1a3d31e3SAndroid Build Coastguard Worker void *p_live_alloc(void)
109*1a3d31e3SAndroid Build Coastguard Worker {
110*1a3d31e3SAndroid Build Coastguard Worker 	size_t sz = sizeof(struct rb_root);
111*1a3d31e3SAndroid Build Coastguard Worker 	return memset(malloc(sz), 0, sz);
112*1a3d31e3SAndroid Build Coastguard Worker }
113*1a3d31e3SAndroid Build Coastguard Worker 
p_live_free(void * p)114*1a3d31e3SAndroid Build Coastguard Worker void p_live_free(void *p)
115*1a3d31e3SAndroid Build Coastguard Worker {
116*1a3d31e3SAndroid Build Coastguard Worker 	free(p);
117*1a3d31e3SAndroid Build Coastguard Worker }
118*1a3d31e3SAndroid Build Coastguard Worker 
p_live_add(struct d_info * dip,__u64 dt,__u64 ct)119*1a3d31e3SAndroid Build Coastguard Worker void p_live_add(struct d_info *dip, __u64 dt, __u64 ct)
120*1a3d31e3SAndroid Build Coastguard Worker {
121*1a3d31e3SAndroid Build Coastguard Worker 	__p_live_add(dip->p_live_handle, dt, ct);
122*1a3d31e3SAndroid Build Coastguard Worker 	__p_live_add(&p_live_root, dt, ct);
123*1a3d31e3SAndroid Build Coastguard Worker }
124*1a3d31e3SAndroid Build Coastguard Worker 
p_live_visit(struct rb_node * n,struct get_info * gip)125*1a3d31e3SAndroid Build Coastguard Worker static void p_live_visit(struct rb_node *n, struct get_info *gip)
126*1a3d31e3SAndroid Build Coastguard Worker {
127*1a3d31e3SAndroid Build Coastguard Worker 	struct p_live *plp = rb_entry(n, struct p_live, rb_node);
128*1a3d31e3SAndroid Build Coastguard Worker 
129*1a3d31e3SAndroid Build Coastguard Worker 	if (n->rb_left)
130*1a3d31e3SAndroid Build Coastguard Worker 		p_live_visit(n->rb_left, gip);
131*1a3d31e3SAndroid Build Coastguard Worker 
132*1a3d31e3SAndroid Build Coastguard Worker 	if (gip->ofp) {
133*1a3d31e3SAndroid Build Coastguard Worker 		float y0 = gip->base_y;
134*1a3d31e3SAndroid Build Coastguard Worker 		float y1 = gip->base_y + 0.9;
135*1a3d31e3SAndroid Build Coastguard Worker 
136*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(gip->ofp, "%.9lf %.1f\n", gip->last_0, y0);
137*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(gip->ofp, "%.9lf %.1f\n", BIT_TIME(plp->dt), y0);
138*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(gip->ofp, "%.9lf %.1f\n", BIT_TIME(plp->dt), y1);
139*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(gip->ofp, "%.9lf %.1f\n", BIT_TIME(plp->ct), y1);
140*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(gip->ofp, "%.9lf %.1f\n", BIT_TIME(plp->ct), y0);
141*1a3d31e3SAndroid Build Coastguard Worker 		gip->last_0 = BIT_TIME(plp->ct);
142*1a3d31e3SAndroid Build Coastguard Worker 	}
143*1a3d31e3SAndroid Build Coastguard Worker 
144*1a3d31e3SAndroid Build Coastguard Worker 	gip->plip->nlives++;
145*1a3d31e3SAndroid Build Coastguard Worker 	gip->tot_live += (plp->ct - plp->dt);
146*1a3d31e3SAndroid Build Coastguard Worker 
147*1a3d31e3SAndroid Build Coastguard Worker 	if (gip->t_start < 0.0 || plp->dt < gip->t_start)
148*1a3d31e3SAndroid Build Coastguard Worker 		gip->t_start = plp->dt;
149*1a3d31e3SAndroid Build Coastguard Worker 	if (gip->t_end < 0.0 || plp->ct > gip->t_end)
150*1a3d31e3SAndroid Build Coastguard Worker 		gip->t_end = plp->ct;
151*1a3d31e3SAndroid Build Coastguard Worker 
152*1a3d31e3SAndroid Build Coastguard Worker 	if (n->rb_right)
153*1a3d31e3SAndroid Build Coastguard Worker 		p_live_visit(n->rb_right, gip);
154*1a3d31e3SAndroid Build Coastguard Worker }
155*1a3d31e3SAndroid Build Coastguard Worker 
p_live_get(struct d_info * dip,int base_y)156*1a3d31e3SAndroid Build Coastguard Worker struct p_live_info *p_live_get(struct d_info *dip, int base_y)
157*1a3d31e3SAndroid Build Coastguard Worker {
158*1a3d31e3SAndroid Build Coastguard Worker 	FILE *ofp = do_open(dip);
159*1a3d31e3SAndroid Build Coastguard Worker 	static struct p_live_info pli;
160*1a3d31e3SAndroid Build Coastguard Worker 	struct p_live_info *plip = &pli;
161*1a3d31e3SAndroid Build Coastguard Worker 	struct get_info gi = {
162*1a3d31e3SAndroid Build Coastguard Worker 		.plip = plip,
163*1a3d31e3SAndroid Build Coastguard Worker 		.t_start = 0.0,
164*1a3d31e3SAndroid Build Coastguard Worker 		.t_end = 0.0,
165*1a3d31e3SAndroid Build Coastguard Worker 		.ofp = ofp,
166*1a3d31e3SAndroid Build Coastguard Worker 		.base_y = base_y,
167*1a3d31e3SAndroid Build Coastguard Worker 	};
168*1a3d31e3SAndroid Build Coastguard Worker 	struct rb_root *root = (dip) ? dip->p_live_handle : &p_live_root;
169*1a3d31e3SAndroid Build Coastguard Worker 
170*1a3d31e3SAndroid Build Coastguard Worker 	memset(plip, 0, sizeof(*plip));
171*1a3d31e3SAndroid Build Coastguard Worker 	if (root->rb_node)
172*1a3d31e3SAndroid Build Coastguard Worker 		p_live_visit(root->rb_node, &gi);
173*1a3d31e3SAndroid Build Coastguard Worker 
174*1a3d31e3SAndroid Build Coastguard Worker 	if (plip->nlives == 0) {
175*1a3d31e3SAndroid Build Coastguard Worker 		plip->avg_live = plip->avg_lull = plip->p_live = 0.0;
176*1a3d31e3SAndroid Build Coastguard Worker 	}
177*1a3d31e3SAndroid Build Coastguard Worker 	else if (plip->nlives == 1) {
178*1a3d31e3SAndroid Build Coastguard Worker 		plip->avg_lull = 0.0;
179*1a3d31e3SAndroid Build Coastguard Worker 		plip->p_live = 100.0;
180*1a3d31e3SAndroid Build Coastguard Worker 	}
181*1a3d31e3SAndroid Build Coastguard Worker 	else {
182*1a3d31e3SAndroid Build Coastguard Worker 		double t_time = BIT_TIME(gi.t_end - gi.t_start);
183*1a3d31e3SAndroid Build Coastguard Worker 		double tot_live = BIT_TIME(gi.tot_live);
184*1a3d31e3SAndroid Build Coastguard Worker 
185*1a3d31e3SAndroid Build Coastguard Worker 		plip->p_live = 100.0 * (tot_live / t_time);
186*1a3d31e3SAndroid Build Coastguard Worker 		plip->avg_live = tot_live / plip->nlives;
187*1a3d31e3SAndroid Build Coastguard Worker 		plip->avg_lull = (t_time - tot_live) / (plip->nlives - 1);
188*1a3d31e3SAndroid Build Coastguard Worker 	}
189*1a3d31e3SAndroid Build Coastguard Worker 
190*1a3d31e3SAndroid Build Coastguard Worker 	return plip;
191*1a3d31e3SAndroid Build Coastguard Worker }
192*1a3d31e3SAndroid Build Coastguard Worker 
p_live_exit(void)193*1a3d31e3SAndroid Build Coastguard Worker void p_live_exit(void)
194*1a3d31e3SAndroid Build Coastguard Worker {
195*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p, *q;
196*1a3d31e3SAndroid Build Coastguard Worker 
197*1a3d31e3SAndroid Build Coastguard Worker 	list_for_each_safe(p, q, &all_p_lives) {
198*1a3d31e3SAndroid Build Coastguard Worker 		struct p_live *plp = list_entry(p, struct p_live, head);
199*1a3d31e3SAndroid Build Coastguard Worker 
200*1a3d31e3SAndroid Build Coastguard Worker 		list_del(&plp->head);
201*1a3d31e3SAndroid Build Coastguard Worker 		free(plp);
202*1a3d31e3SAndroid Build Coastguard Worker 	}
203*1a3d31e3SAndroid Build Coastguard Worker }
204