Merge branch 'master' of ssh://git.kernel.dk/data/git/blktrace
[blktrace.git] / btt / proc.c
CommitLineData
63eba147
JA
1/*
2 * blktrace output analysis: generate a timeline & gather statistics
3 *
4 * Copyright (C) 2006 Alan D. Brunelle <Alan.Brunelle@hp.com>
5 *
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.
10 *
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.
15 *
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
19 *
20 */
21#include <string.h>
22
23#include "globals.h"
24
6eb42155
ADB
25struct pn_info {
26 struct rb_node rb_node;
27 struct p_info *pip;
28 union {
29 char *name;
30 __u32 pid;
31 } u;
32};
33
34struct rb_root root_pid, root_name;
63eba147 35
6eb42155 36struct p_info * __find_process_pid(__u32 pid)
63eba147 37{
6eb42155
ADB
38 struct pn_info *this;
39 struct rb_node *n = root_pid.rb_node;
40
41 while (n) {
42 this = rb_entry(n, struct pn_info, rb_node);
43 if (pid < this->u.pid)
44 n = n->rb_left;
45 else if (pid > this->u.pid)
46 n = n->rb_right;
47 else
48 return this->pip;
49 }
63eba147 50
6eb42155 51 return NULL;
63eba147
JA
52}
53
6eb42155 54struct p_info *__find_process_name(char *name)
63eba147 55{
6eb42155
ADB
56 int cmp;
57 struct pn_info *this;
58 struct rb_node *n = root_name.rb_node;
59
60 while (n) {
61 this = rb_entry(n, struct pn_info, rb_node);
62 cmp = strcmp(name, this->u.name);
63 if (cmp < 0)
64 n = n->rb_left;
65 else if (cmp > 0)
66 n = n->rb_right;
67 else
68 return this->pip;
63eba147
JA
69 }
70
71 return NULL;
72}
73
6eb42155 74struct p_info *find_process(__u32 pid, char *name)
63eba147 75{
6eb42155 76 struct p_info *pip;
63eba147 77
6eb42155
ADB
78 if (pid != ((__u32)-1) && ((pip = __find_process_pid(pid)) != NULL))
79 return pip;
63eba147 80
6eb42155
ADB
81 if (name)
82 return __find_process_name(name);
63eba147 83
6eb42155 84 return NULL;
63eba147
JA
85}
86
6eb42155 87static void insert_pid(struct p_info *that)
63eba147 88{
6eb42155
ADB
89 struct pn_info *this;
90 struct rb_node *parent = NULL;
91 struct rb_node **p = &root_pid.rb_node;
92
93 while (*p) {
94 parent = *p;
95 this = rb_entry(parent, struct pn_info, rb_node);
96
97 if (that->pid < this->u.pid)
98 p = &(*p)->rb_left;
99 else if (that->pid > this->u.pid)
100 p = &(*p)->rb_right;
101 else {
102 ASSERT(strcmp(that->name, this->pip->name) == 0);
103 return; // Already there
104 }
105 }
106
107 this = malloc(sizeof(struct pn_info));
108 this->u.pid = that->pid;
109 this->pip = that;
110
111 rb_link_node(&this->rb_node, parent, p);
112 rb_insert_color(&this->rb_node, &root_pid);
63eba147
JA
113}
114
6eb42155 115static void insert_name(struct p_info *that)
63eba147 116{
6eb42155
ADB
117 int cmp;
118 struct pn_info *this;
119 struct rb_node *parent = NULL;
120 struct rb_node **p = &root_name.rb_node;
121
122 while (*p) {
123 parent = *p;
124 this = rb_entry(parent, struct pn_info, rb_node);
125 cmp = strcmp(that->name, this->u.name);
126
127 if (cmp < 0)
128 p = &(*p)->rb_left;
129 else if (cmp > 0)
130 p = &(*p)->rb_right;
131 else
132 return; // Already there...
133 }
63eba147 134
6eb42155
ADB
135 this = malloc(sizeof(struct pn_info));
136 this->u.name = strdup(that->name);
137 this->pip = that;
63eba147 138
6eb42155
ADB
139 rb_link_node(&this->rb_node, parent, p);
140 rb_insert_color(&this->rb_node, &root_name);
141}
63eba147 142
6eb42155
ADB
143static void insert(struct p_info *pip)
144{
145 insert_pid(pip);
146 insert_name(pip);
63eba147
JA
147}
148
149void add_process(__u32 pid, char *name)
150{
151 struct p_info *pip = find_process(pid, name);
152
153 if (pip == NULL) {
6eb42155 154 size_t len = sizeof(struct p_info) + strlen(name) + 1;
63eba147 155
6eb42155
ADB
156 pip = memset(malloc(len), 0, len);
157 pip->pid = pid;
63eba147 158 init_region(&pip->regions);
6eb42155
ADB
159 pip->last_q = (__u64)-1;
160 strcpy(pip->name, name);
161
162 insert(pip);
63eba147
JA
163 }
164}
165
166void pip_update_q(struct io *iop)
167{
168 if (iop->pip) {
169 update_lq(&iop->pip->last_q, &iop->pip->avgs.q2q, iop->t.time);
170 update_qregion(&iop->pip->regions, iop->t.time);
171 }
172}
6eb42155
ADB
173
174void __foreach(struct rb_node *n, void (*f)(struct p_info *, void *), void *arg)
175{
176 if (n) {
177 __foreach(n->rb_left, f, arg);
178 f(rb_entry(n, struct pn_info, rb_node)->pip, arg);
179 __foreach(n->rb_right, f, arg);
180 }
181}
182
183void pip_foreach_out(void (*f)(struct p_info *, void *), void *arg)
184{
185 if (exes == NULL)
186 __foreach(root_name.rb_node, f, arg);
187 else {
188 struct p_info *pip;
189 char *exe, *p, *next, *exes_save = strdup(exes);
190
191 p = exes_save;
192 while (exes_save != NULL) {
193 exe = exes_save;
194 if ((next = strchr(exes_save, ',')) != NULL) {
195 *next = '\0';
196 exes_save = next+1;
197 }
198 else
199 exes_save = NULL;
200
201 pip = __find_process_name(exe);
202 if (pip)
203 f(pip, arg);
204 }
205 }
206}