| /** |
| * @file opd_sample_files.c |
| * Management of sample files |
| * |
| * @remark Copyright 2002 OProfile authors |
| * @remark Read the file COPYING |
| * |
| * @author John Levon |
| * @author Philippe Elie |
| */ |
| |
| #include <sys/types.h> |
| |
| #include "opd_sample_files.h" |
| #include "opd_image.h" |
| #include "opd_printf.h" |
| #include "opd_events.h" |
| #include "oprofiled.h" |
| |
| #include "op_sample_file.h" |
| #include "op_file.h" |
| #include "op_config.h" |
| #include "op_mangle.h" |
| #include "op_events.h" |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <errno.h> |
| |
| /** All sfiles are on this list. */ |
| static LIST_HEAD(lru_list); |
| |
| /* this value probably doesn't matter too much */ |
| #define LRU_AMOUNT 1000 |
| static int opd_24_sfile_lru_clear(void) |
| { |
| struct list_head * pos; |
| struct list_head * pos2; |
| struct opd_24_sfile * sfile; |
| int amount = LRU_AMOUNT; |
| |
| verbprintf(vsfile, "image lru clear\n"); |
| |
| if (list_empty(&lru_list)) |
| return 1; |
| |
| list_for_each_safe(pos, pos2, &lru_list) { |
| if (!--amount) |
| break; |
| sfile = list_entry(pos, struct opd_24_sfile, lru_next); |
| odb_close(&sfile->sample_file); |
| list_del_init(&sfile->lru_next); |
| } |
| |
| return 0; |
| } |
| |
| |
| void opd_24_sfile_lru(struct opd_24_sfile * sfile) |
| { |
| list_del(&sfile->lru_next); |
| list_add_tail(&sfile->lru_next, &lru_list); |
| } |
| |
| |
| static char * opd_mangle_filename(struct opd_image const * image, int counter, |
| int cpu_nr) |
| { |
| char * mangled; |
| struct mangle_values values; |
| struct opd_event * event = find_counter_event(counter); |
| |
| values.flags = 0; |
| if (image->kernel) |
| values.flags |= MANGLE_KERNEL; |
| |
| if (separate_thread) { |
| values.flags |= MANGLE_TGID | MANGLE_TID; |
| values.tid = image->tid; |
| values.tgid = image->tgid; |
| } |
| |
| if (separate_cpu) { |
| values.flags |= MANGLE_CPU; |
| values.cpu = cpu_nr; |
| } |
| |
| values.event_name = event->name; |
| values.count = event->count; |
| values.unit_mask = event->um; |
| |
| values.image_name = image->name; |
| values.dep_name = separate_lib && image->app_name |
| ? image->app_name : image->name; |
| |
| mangled = op_mangle_filename(&values); |
| |
| return mangled; |
| } |
| |
| |
| int opd_open_24_sample_file(struct opd_image * image, int counter, int cpu_nr) |
| { |
| char * mangled; |
| struct opd_24_sfile * sfile; |
| int err; |
| |
| mangled = opd_mangle_filename(image, counter, cpu_nr); |
| |
| verbprintf(vsfile, "Opening \"%s\"\n", mangled); |
| |
| create_path(mangled); |
| |
| sfile = image->sfiles[cpu_nr][counter]; |
| if (!sfile) { |
| sfile = malloc(sizeof(struct opd_24_sfile)); |
| list_init(&sfile->lru_next); |
| odb_init(&sfile->sample_file); |
| image->sfiles[cpu_nr][counter] = sfile; |
| } |
| |
| list_del(&sfile->lru_next); |
| list_add_tail(&sfile->lru_next, &lru_list); |
| |
| retry: |
| err = odb_open(&sfile->sample_file, mangled, ODB_RDWR, |
| sizeof(struct opd_header)); |
| |
| /* This can naturally happen when racing against opcontrol --reset. */ |
| if (err) { |
| if (err == EMFILE) { |
| if (opd_24_sfile_lru_clear()) { |
| printf("LRU cleared but odb_open() fails for %s.\n", mangled); |
| abort(); |
| } |
| goto retry; |
| } |
| |
| fprintf(stderr, "oprofiled: open of %s failed: %s\n", |
| mangled, strerror(err)); |
| goto out; |
| } |
| |
| fill_header(odb_get_data(&sfile->sample_file), counter, 0, 0, |
| image->kernel, 0, 0, 0, image->mtime); |
| |
| out: |
| free(mangled); |
| return err; |
| } |
| |
| |
| void opd_sync_samples_files(void) |
| { |
| struct list_head * pos; |
| struct opd_24_sfile * sfile; |
| |
| list_for_each(pos, &lru_list) { |
| sfile = list_entry(pos, struct opd_24_sfile, lru_next); |
| odb_sync(&sfile->sample_file); |
| } |
| } |
| |
| |
| void opd_close_image_samples_files(struct opd_image * image) |
| { |
| uint i, j; |
| for (i = 0 ; i < op_nr_counters ; ++i) { |
| for (j = 0; j < NR_CPUS; ++j) { |
| if (image->sfiles[j] && image->sfiles[j][i]) { |
| odb_close(&image->sfiles[j][i]->sample_file); |
| list_del(&image->sfiles[j][i]->lru_next); |
| free(image->sfiles[j][i]); |
| image->sfiles[j][i] = 0; |
| } |
| } |
| } |
| } |