blob: 2f9b38cbf1ccdece6bf14b407ab1a5d420a931ad [file] [log] [blame]
Mike Dodd8cfa7022010-11-17 11:12:26 -08001/**
2 * @file opd_proc.c
3 * Management of processes
4 *
5 * @remark Copyright 2002 OProfile authors
6 * @remark Read the file COPYING
7 *
8 * @author John Levon
9 * @author Philippe Elie
10 */
11
12#include "op_hw_config.h"
13#include "opd_proc.h"
14#include "opd_image.h"
15#include "opd_mapping.h"
16#include "opd_sample_files.h"
17#include "opd_kernel.h"
18#include "opd_24_stats.h"
19#include "opd_printf.h"
20#include "oprofiled.h"
21
22#include "op_interface.h"
23#include "op_libiberty.h"
24
25#include <sys/types.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
30/* size of process hash table */
31#define OPD_MAX_PROC_HASH 1024
32
33extern int cpu_number;
34
35/* hash of process lists */
36static struct list_head opd_procs[OPD_MAX_PROC_HASH];
37
38/* statistics purpose */
39static int nr_procs;
40
41
42void opd_init_procs(void)
43{
44 int i;
45 for (i = 0; i < OPD_MAX_PROC_HASH; i++)
46 list_init(&opd_procs[i]);
47}
48
49
50int opd_get_nr_procs(void)
51{
52 return nr_procs;
53}
54
55
56/**
57 * proc_hash - hash pid value
58 * @param tid pid value to hash
59 *
60 */
61inline static uint proc_hash(pid_t tid)
62{
63 /* FIXME: hash tgid too! */
64 return ((tid >> 4) ^ (tid)) % OPD_MAX_PROC_HASH;
65}
66
67
68struct opd_proc * opd_new_proc(pid_t tid, pid_t tgid)
69{
70 struct opd_proc * proc;
71
72 nr_procs++;
73 proc = xmalloc(sizeof(struct opd_proc));
74 list_init(&proc->maps);
75 proc->name = NULL;
76 proc->tid = tid;
77 proc->tgid = tgid;
78 proc->dead = 0;
79 proc->accessed = 0;
80 list_add(&proc->next, &opd_procs[proc_hash(tid)]);
81 return proc;
82}
83
84
85struct opd_proc * opd_get_proc(pid_t tid, pid_t tgid)
86{
87 struct opd_proc * proc;
88 uint hash = proc_hash(tid);
89 struct list_head * pos, *pos2;
90
91 opd_24_stats[OPD_PROC_QUEUE_ACCESS]++;
92 list_for_each_safe(pos, pos2, &opd_procs[hash]) {
93 opd_24_stats[OPD_PROC_QUEUE_DEPTH]++;
94 proc = list_entry(pos, struct opd_proc, next);
95 if (tid == proc->tid && tgid == proc->tgid) {
96 /* LRU to head */
97 list_del(&proc->next);
98 list_add(&proc->next, &opd_procs[hash]);
99 return proc;
100 }
101 }
102
103 return NULL;
104}
105
106
107/**
108 * verb_show_sample - print the sample out to the log
109 * @param offset the offset value
110 * @param map map to print
111 */
112inline static void
113verb_show_sample(unsigned long offset, struct opd_map * map)
114{
115 verbprintf(vsamples, "DO_PUT_SAMPLE : calc offset 0x%.8lx, "
116 "map start 0x%.8lx, end 0x%.8lx, offset 0x%.8lx, name \"%s\"\n",
117 offset, map->start, map->end, map->offset,
118 map->image->name);
119}
120
121
122void opd_put_image_sample(struct opd_image * image, unsigned long offset,
123 u32 counter)
124{
125 struct opd_24_sfile * sfile;
126 int err;
127
128 if (image->ignored)
129 return;
130
131 if (!image->sfiles[cpu_number]) {
132 image->sfiles[cpu_number] =
133 xcalloc(OP_MAX_COUNTERS, sizeof(struct op_24_sfile *));
134 }
135 sfile = image->sfiles[cpu_number][counter];
136
137 if (!sfile || !odb_open_count(&sfile->sample_file)) {
138 if (opd_open_24_sample_file(image, counter, cpu_number)) {
139 /* opd_open_24_sample_file output an error message */
140 opd_24_stats[OPD_LOST_SAMPLEFILE]++;
141 return;
142 }
143 sfile = image->sfiles[cpu_number][counter];
144 }
145
146 err = odb_update_node(&sfile->sample_file, offset);
147 if (err) {
148 fprintf(stderr, "%s\n", strerror(err));
149 abort();
150 }
151
152 opd_24_sfile_lru(sfile);
153}
154
155
156/**
157 * opd_lookup_maps - lookup a proc mappings for a sample
158 * @param proc proc to lookup
159 * @param sample sample to lookup
160 *
161 * iterate through the proc maps searching the mapping which owns sample
162 * if sucessful sample count will be updated and we return non-zero
163 */
164static int opd_lookup_maps(struct opd_proc * proc,
165 struct op_sample const * sample)
166{
167 struct list_head * pos;
168
169 proc->accessed = 1;
170
171 opd_24_stats[OPD_MAP_ARRAY_ACCESS]++;
172 list_for_each(pos, &proc->maps) {
173 struct opd_map * map = list_entry(pos, struct opd_map, next);
174 if (opd_is_in_map(map, sample->eip)) {
175 unsigned long offset = opd_map_offset(map, sample->eip);
176 if (map->image != NULL) {
177 verb_show_sample(offset, map);
178 opd_put_image_sample(map->image, offset, sample->counter);
179 }
180 opd_24_stats[OPD_PROCESS]++;
181 return 1;
182 }
183 opd_24_stats[OPD_MAP_ARRAY_DEPTH]++;
184 }
185
186 return 0;
187}
188
189
190void opd_put_sample(struct op_sample const * sample)
191{
192 struct opd_proc * proc;
193 int in_kernel_eip = opd_eip_is_kernel(sample->eip);
194
195 opd_24_stats[OPD_SAMPLES]++;
196
197 verbprintf(vsamples, "DO_PUT_SAMPLE: c%d, EIP 0x%.8lx, tgid %.6d pid %.6d\n",
198 sample->counter, sample->eip, sample->tgid, sample->pid);
199
200 if (!separate_kernel && in_kernel_eip) {
201 opd_handle_kernel_sample(sample->eip, sample->counter);
202 return;
203 }
204
205 if (!(proc = opd_get_proc(sample->pid, sample->tgid))) {
206 if (in_kernel_eip || no_vmlinux) {
207 /* idle task get a 0 pid and is hidden we can never get
208 * a proc so on we fall back to put sample in vmlinux
209 * or module samples files. Here we will catch also
210 * sample for newly created kernel thread, currently
211 * we can handle properly only kenel thread created
212 * at daemon startup time */
213 opd_handle_kernel_sample(sample->eip, sample->counter);
214 } else {
215 verbprintf(vmisc, "No proc info for tgid %.6d pid %.6d.\n",
216 sample->tgid, sample->pid);
217 opd_24_stats[OPD_LOST_PROCESS]++;
218 }
219 return;
220 }
221
222 if (opd_lookup_maps(proc, sample))
223 return;
224
225 if (in_kernel_eip) {
226 opd_add_kernel_map(proc, sample->eip);
227 if (opd_lookup_maps(proc, sample))
228 return;
229 }
230
231 /* couldn't locate it */
232 verbprintf(vsamples, "Couldn't find map for pid %.6d, EIP 0x%.8lx.\n",
233 sample->pid, sample->eip);
234 opd_24_stats[OPD_LOST_MAP_PROCESS]++;
235}
236
237
238void opd_handle_fork(struct op_note const * note)
239{
240 struct opd_proc * old;
241 struct opd_proc * proc;
242 struct list_head * pos;
243
244 verbprintf(vmisc, "DO_FORK: from %d, %d to %ld, %ld\n", note->pid, note->tgid,
245 note->addr, note->len);
246
247 old = opd_get_proc(note->pid, note->tgid);
248
249 /* we can quite easily get a fork() after the execve() because the
250 * notifications are racy. In particular, the fork notification is
251 * done on parent return (so we know the pid), but this will often be
252 * after the execve is done by the child.
253 *
254 * So we only create a new setup if it doesn't exist already, allowing
255 * both the clone() and the execve() cases to work.
256 */
257 if (opd_get_proc(note->addr, note->len))
258 return;
259
260 /* eip/len is actually tid/tgid of new process */
261 proc = opd_new_proc(note->addr, note->len);
262
263 if (!old)
264 return;
265
266 /* copy the maps */
267 list_for_each(pos, &old->maps) {
268 struct opd_map * map = list_entry(pos, struct opd_map, next);
269 if (!separate_thread) {
270 opd_add_mapping(proc, map->image, map->start,
271 map->offset, map->end);
272 } else {
273 /* when separating thread we can't create blindly a new
274 * image e.g. pid re-use, multiple mapping with the
275 * same mapping name etc. */
276 struct opd_image * image =
277 opd_get_image(map->image->name, old->name,
278 map->image->kernel, note->addr, note->len);
279 opd_add_mapping(proc, image, map->start, map->offset,
280 map->end);
281 }
282 }
283}
284
285
286void opd_handle_exec(pid_t tid, pid_t tgid)
287{
288 struct opd_proc * proc;
289
290 verbprintf(vmisc, "DO_EXEC: pid %u %u\n", tid, tgid);
291
292 /* There is a race for samples received between fork/exec sequence.
293 * These samples belong to the old mapping but we can not say if
294 * samples has been received before the exec or after. This explains
295 * the message "Couldn't find map for ..." in verbose mode.
296 *
297 * Unhappily, it is difficult to get an estimation of these misplaced
298 * samples, the error message can count only out of mapping samples but
299 * not samples between the race and inside the mapping of the exec'ed
300 * process :/.
301 *
302 * Trying to save old mapping is not correct due the above reason. The
303 * only manner to handle this is to flush the module samples hash table
304 * after each fork which is unacceptable for performance reasons */
305 proc = opd_get_proc(tid, tgid);
306 if (proc) {
307 opd_kill_maps(proc);
308 /* proc->name will be set when the next mapping occurs */
309 free((char *)proc->name);
310 proc->name = NULL;
311 } else {
312 opd_new_proc(tid, tgid);
313 }
314}
315
316
317void opd_handle_exit(struct op_note const * note)
318{
319 struct opd_proc * proc;
320
321 verbprintf(vmisc, "DO_EXIT: process %d\n", note->pid);
322
323 proc = opd_get_proc(note->pid, note->tgid);
324 if (proc) {
325 proc->dead = 1;
326 proc->accessed = 1;
327 } else {
328 verbprintf(vmisc, "unknown proc %u just exited.\n", note->pid);
329 }
330}
331
332
333typedef void (*opd_proc_cb)(struct opd_proc *);
334
335/**
336 * @param proc_cb callback to apply onto each existing proc struct
337 *
338 * the callback receive a struct opd_proc * (not a const struct) and is
339 * allowed to freeze the proc struct itself.
340 */
341static void opd_for_each_proc(opd_proc_cb proc_cb)
342{
343 struct list_head * pos;
344 struct list_head * pos2;
345 int i;
346
347 for (i = 0; i < OPD_MAX_PROC_HASH; ++i) {
348 list_for_each_safe(pos, pos2, &opd_procs[i]) {
349 struct opd_proc * proc =
350 list_entry(pos, struct opd_proc, next);
351 proc_cb(proc);
352 }
353 }
354}
355
356
357/**
358 * opd_delete_proc - delete a process
359 * @param proc process to delete
360 *
361 * Remove the process proc from the process list and free
362 * the associated structures.
363 */
364static void opd_delete_proc(struct opd_proc * proc)
365{
366 --nr_procs;
367 list_del(&proc->next);
368 opd_kill_maps(proc);
369 if (proc->name)
370 free((char *)proc->name);
371 free(proc);
372}
373
374
375void opd_proc_cleanup(void)
376{
377 opd_for_each_proc(opd_delete_proc);
378}
379
380
381/**
382 * opd_age_proc - age a struct opd_proc
383 * @param proc proc to age
384 *
385 * age dead proc in such way if a proc doesn't receive any samples
386 * between two age_proc the opd_proc struct is deleted
387 */
388static void opd_age_proc(struct opd_proc * proc)
389{
390 // delay death whilst its still being accessed
391 if (proc->dead) {
392 proc->dead += proc->accessed;
393 proc->accessed = 0;
394 if (--proc->dead == 0)
395 opd_delete_proc(proc);
396 }
397}
398
399
400void opd_age_procs(void)
401{
402 opd_for_each_proc(opd_age_proc);
403}
404
405
406/**
407 * opd_remove_kernel_mapping - remove all kernel mapping for an opd_proc
408 * @param proc proc where mappings must be updated.
409 *
410 * invalidate (by removing them) all kernel mapping. This function do nothing
411 * when separate_kernel == 0 because we don't add mapping for kernel
412 * sample in proc struct.
413 */
414static void opd_remove_kernel_mapping(struct opd_proc * proc)
415{
416 struct list_head * pos, * pos2;
417
418 list_for_each_safe(pos, pos2, &proc->maps) {
419 struct opd_map * map = list_entry(pos, struct opd_map, next);
420 if (opd_eip_is_kernel(map->start + map->offset)) {
421 list_del(pos);
422 opd_delete_image(map->image);
423 free(map);
424 }
425 }
426}
427
428
429void opd_clear_kernel_mapping(void)
430{
431 opd_for_each_proc(opd_remove_kernel_mapping);
432}