opd_proc.c revision 8cfa702f803c5ef6a2b062a489a1b2cf66b45b5e
1/**
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}
433