• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
33 extern int cpu_number;
34 
35 /* hash of process lists */
36 static struct list_head opd_procs[OPD_MAX_PROC_HASH];
37 
38 /* statistics purpose */
39 static int nr_procs;
40 
41 
opd_init_procs(void)42 void 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 
opd_get_nr_procs(void)50 int 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  */
proc_hash(pid_t tid)61 inline 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 
opd_new_proc(pid_t tid,pid_t tgid)68 struct 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 
opd_get_proc(pid_t tid,pid_t tgid)85 struct 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  */
112 inline static void
verb_show_sample(unsigned long offset,struct opd_map * map)113 verb_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 
opd_put_image_sample(struct opd_image * image,unsigned long offset,u32 counter)122 void 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  */
opd_lookup_maps(struct opd_proc * proc,struct op_sample const * sample)164 static 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 
opd_put_sample(struct op_sample const * sample)190 void 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 
opd_handle_fork(struct op_note const * note)238 void 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 
opd_handle_exec(pid_t tid,pid_t tgid)286 void 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 
opd_handle_exit(struct op_note const * note)317 void 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 
333 typedef 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  */
opd_for_each_proc(opd_proc_cb proc_cb)341 static 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  */
opd_delete_proc(struct opd_proc * proc)364 static 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 
opd_proc_cleanup(void)375 void 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  */
opd_age_proc(struct opd_proc * proc)388 static 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 
opd_age_procs(void)400 void 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  */
opd_remove_kernel_mapping(struct opd_proc * proc)414 static 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 
opd_clear_kernel_mapping(void)429 void opd_clear_kernel_mapping(void)
430 {
431 	opd_for_each_proc(opd_remove_kernel_mapping);
432 }
433