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