Home | History | Annotate | Download | only in liblegacy
      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 
     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 
     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  */
     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 
     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 
     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
    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 
    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  */
    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 
    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 
    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 
    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 
    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  */
    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  */
    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 
    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  */
    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 
    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  */
    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 
    429 void opd_clear_kernel_mapping(void)
    430 {
    431 	opd_for_each_proc(opd_remove_kernel_mapping);
    432 }
    433