Home | History | Annotate | Download | only in liblegacy
      1 /**
      2  * @file opd_sample_files.c
      3  * Management of sample files
      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 <sys/types.h>
     13 
     14 #include "opd_sample_files.h"
     15 #include "opd_image.h"
     16 #include "opd_printf.h"
     17 #include "opd_events.h"
     18 #include "oprofiled.h"
     19 
     20 #include "op_sample_file.h"
     21 #include "op_file.h"
     22 #include "op_config.h"
     23 #include "op_mangle.h"
     24 #include "op_events.h"
     25 
     26 #include <stdio.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 #include <errno.h>
     30 
     31 /** All sfiles are on this list. */
     32 static LIST_HEAD(lru_list);
     33 
     34 /* this value probably doesn't matter too much */
     35 #define LRU_AMOUNT 1000
     36 static int opd_24_sfile_lru_clear(void)
     37 {
     38 	struct list_head * pos;
     39 	struct list_head * pos2;
     40 	struct opd_24_sfile * sfile;
     41 	int amount = LRU_AMOUNT;
     42 
     43 	verbprintf(vsfile, "image lru clear\n");
     44 
     45 	if (list_empty(&lru_list))
     46 		return 1;
     47 
     48 	list_for_each_safe(pos, pos2, &lru_list) {
     49 		if (!--amount)
     50 			break;
     51 		sfile = list_entry(pos, struct opd_24_sfile, lru_next);
     52 		odb_close(&sfile->sample_file);
     53 		list_del_init(&sfile->lru_next);
     54 	}
     55 
     56 	return 0;
     57 }
     58 
     59 
     60 void opd_24_sfile_lru(struct opd_24_sfile * sfile)
     61 {
     62 	list_del(&sfile->lru_next);
     63 	list_add_tail(&sfile->lru_next, &lru_list);
     64 }
     65 
     66 
     67 static char * opd_mangle_filename(struct opd_image const * image, int counter,
     68                                   int cpu_nr)
     69 {
     70 	char * mangled;
     71 	struct mangle_values values;
     72 	struct opd_event * event = find_counter_event(counter);
     73 
     74 	values.flags = 0;
     75 	if (image->kernel)
     76 		values.flags |= MANGLE_KERNEL;
     77 
     78 	if (separate_thread) {
     79 		values.flags |= MANGLE_TGID | MANGLE_TID;
     80 		values.tid = image->tid;
     81 		values.tgid = image->tgid;
     82 	}
     83 
     84 	if (separate_cpu) {
     85 		values.flags |= MANGLE_CPU;
     86 		values.cpu = cpu_nr;
     87 	}
     88 
     89 	values.event_name = event->name;
     90 	values.count = event->count;
     91 	values.unit_mask = event->um;
     92 
     93 	values.image_name = image->name;
     94 	values.dep_name = separate_lib && image->app_name
     95 		? image->app_name : image->name;
     96 
     97 	mangled = op_mangle_filename(&values);
     98 
     99 	return mangled;
    100 }
    101 
    102 
    103 int opd_open_24_sample_file(struct opd_image * image, int counter, int cpu_nr)
    104 {
    105 	char * mangled;
    106 	struct opd_24_sfile * sfile;
    107 	int err;
    108 
    109 	mangled = opd_mangle_filename(image, counter, cpu_nr);
    110 
    111 	verbprintf(vsfile, "Opening \"%s\"\n", mangled);
    112 
    113 	create_path(mangled);
    114 
    115 	sfile = image->sfiles[cpu_nr][counter];
    116 	if (!sfile) {
    117 		sfile = malloc(sizeof(struct opd_24_sfile));
    118 		list_init(&sfile->lru_next);
    119 		odb_init(&sfile->sample_file);
    120 		image->sfiles[cpu_nr][counter] = sfile;
    121 	}
    122 
    123 	list_del(&sfile->lru_next);
    124 	list_add_tail(&sfile->lru_next, &lru_list);
    125 
    126 retry:
    127 	err = odb_open(&sfile->sample_file, mangled, ODB_RDWR,
    128                        sizeof(struct opd_header));
    129 
    130 	/* This can naturally happen when racing against opcontrol --reset. */
    131 	if (err) {
    132 		if (err == EMFILE) {
    133 			if (opd_24_sfile_lru_clear()) {
    134 				printf("LRU cleared but odb_open() fails for %s.\n", mangled);
    135 				abort();
    136 			}
    137 			goto retry;
    138 		}
    139 
    140 		fprintf(stderr, "oprofiled: open of %s failed: %s\n",
    141 		        mangled, strerror(err));
    142 		goto out;
    143 	}
    144 
    145 	fill_header(odb_get_data(&sfile->sample_file), counter, 0, 0,
    146 		    image->kernel, 0, 0, 0, image->mtime);
    147 
    148 out:
    149 	free(mangled);
    150 	return err;
    151 }
    152 
    153 
    154 void opd_sync_samples_files(void)
    155 {
    156 	struct list_head * pos;
    157 	struct opd_24_sfile * sfile;
    158 
    159 	list_for_each(pos, &lru_list) {
    160 		sfile = list_entry(pos, struct opd_24_sfile, lru_next);
    161 		odb_sync(&sfile->sample_file);
    162 	}
    163 }
    164 
    165 
    166 void opd_close_image_samples_files(struct opd_image * image)
    167 {
    168 	uint i, j;
    169 	for (i = 0 ; i < op_nr_counters ; ++i) {
    170 		for (j = 0; j < NR_CPUS; ++j) {
    171 			if (image->sfiles[j] && image->sfiles[j][i]) {
    172 				odb_close(&image->sfiles[j][i]->sample_file);
    173 				list_del(&image->sfiles[j][i]->lru_next);
    174 				free(image->sfiles[j][i]);
    175 				image->sfiles[j][i] = 0;
    176 			}
    177 		}
    178 	}
    179 }
    180