2 * blktrace output analysis: generate a timeline & gather statistics
4 * Copyright (C) 2006 Alan D. Brunelle <Alan.Brunelle@hp.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 struct rb_node rb_node;
34 struct rb_root root_pid, root_name;
36 static void __destroy(struct rb_node *n, int free_name, int free_pip)
39 struct pn_info *pnp = rb_entry(n, struct pn_info, rb_node);
41 __destroy(n->rb_left, free_name, free_pip);
42 __destroy(n->rb_right, free_name, free_pip);
44 if (free_name) free(pnp->u.name);
47 region_exit(&pnp->pip->regions);
54 struct p_info * __find_process_pid(__u32 pid)
57 struct rb_node *n = root_pid.rb_node;
60 this = rb_entry(n, struct pn_info, rb_node);
61 if (pid < this->u.pid)
63 else if (pid > this->u.pid)
72 struct p_info *__find_process_name(char *name)
76 struct rb_node *n = root_name.rb_node;
79 this = rb_entry(n, struct pn_info, rb_node);
80 cmp = strcmp(name, this->u.name);
92 static void insert_pid(struct p_info *that, __u32 pid)
95 struct rb_node *parent = NULL;
96 struct rb_node **p = &root_pid.rb_node;
100 this = rb_entry(parent, struct pn_info, rb_node);
102 if (pid < this->u.pid)
104 else if (pid > this->u.pid)
107 return; // Already there
110 this = malloc(sizeof(struct pn_info));
114 rb_link_node(&this->rb_node, parent, p);
115 rb_insert_color(&this->rb_node, &root_pid);
118 static void insert_name(struct p_info *that)
121 struct pn_info *this;
122 struct rb_node *parent = NULL;
123 struct rb_node **p = &root_name.rb_node;
127 this = rb_entry(parent, struct pn_info, rb_node);
128 cmp = strcmp(that->name, this->u.name);
135 return; // Already there...
138 this = malloc(sizeof(struct pn_info));
139 this->u.name = strdup(that->name);
142 rb_link_node(&this->rb_node, parent, p);
143 rb_insert_color(&this->rb_node, &root_name);
146 static void insert(struct p_info *pip)
148 insert_pid(pip, pip->pid);
152 static inline struct p_info *pip_alloc(void)
154 return memset(malloc(sizeof(struct p_info)), 0, sizeof(struct p_info));
157 struct p_info *find_process(__u32 pid, char *name)
161 if (pid != ((__u32)-1)) {
162 if ((pip = __find_process_pid(pid)) != NULL)
165 pip = __find_process_name(name);
167 if (pip && pid != pip->pid) {
169 * This is a process with the same name
170 * as another, but a different PID.
172 * We'll store a reference in the PID
175 insert_pid(pip, pid);
181 * We're here because we have a pid, and no name, but
182 * we didn't find a process ...
184 * We'll craft one using the pid...
188 sprintf(name, "pid%09u", pid);
189 add_process(pid, name);
190 return __find_process_pid(pid);
193 return __find_process_name(name);
196 void add_process(__u32 pid, char *name)
198 struct p_info *pip = find_process(pid, name);
203 region_init(&pip->regions);
204 pip->last_q = (__u64)-1;
205 pip->name = strdup(name);
211 void pip_update_q(struct io *iop)
214 if (remapper_dev(iop->dip->device))
215 update_lq(&iop->pip->last_q, &iop->pip->avgs.q2q_dm,
218 update_lq(&iop->pip->last_q, &iop->pip->avgs.q2q,
220 update_qregion(&iop->pip->regions, iop->t.time);
224 void __foreach(struct rb_node *n, void (*f)(struct p_info *, void *), void *arg)
227 __foreach(n->rb_left, f, arg);
228 f(rb_entry(n, struct pn_info, rb_node)->pip, arg);
229 __foreach(n->rb_right, f, arg);
233 void pip_foreach_out(void (*f)(struct p_info *, void *), void *arg)
236 __foreach(root_name.rb_node, f, arg);
239 char *exe, *p, *next, *exes_save = strdup(exes);
242 while (exes_save != NULL) {
244 if ((next = strchr(exes_save, ',')) != NULL) {
251 pip = __find_process_name(exe);
260 __destroy(root_pid.rb_node, 0, 0);
261 __destroy(root_name.rb_node, 1, 1);