opd_sample_files.c revision cc2ee177dbb3befca43e36cfc56778b006c3d050
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. */
32static LIST_HEAD(lru_list);
33
34/* this value probably doesn't matter too much */
35#define LRU_AMOUNT 1000
36static 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
60void 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
67static 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
103int 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
126retry:
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, image->mtime);
147
148out:
149	free(mangled);
150	return err;
151}
152
153
154void 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
166void 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