• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
opd_24_sfile_lru_clear(void)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 
opd_24_sfile_lru(struct opd_24_sfile * sfile)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 
opd_mangle_filename(struct opd_image const * image,int counter,int cpu_nr)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 
opd_open_24_sample_file(struct opd_image * image,int counter,int cpu_nr)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 
opd_sync_samples_files(void)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 
opd_close_image_samples_files(struct opd_image * image)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