Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

[189ee5]: daemon / liblegacy / opd_image.c Maximize Restore History

Download this file

opd_image.c    266 lines (216 with data), 6.8 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/**
* @file opd_image.c
* Management of binary images
*
* @remark Copyright 2002 OProfile authors
* @remark Read the file COPYING
*
* @author John Levon
* @author Philippe Elie
*/
#include "opd_image.h"
#include "opd_printf.h"
#include "opd_sample_files.h"
#include "opd_24_stats.h"
#include "oprofiled.h"
#include "op_file.h"
#include "op_config_24.h"
#include "op_libiberty.h"
#include "op_string.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
/* maintained for statistics purpose only */
static int nr_images;
/* list of images */
#define OPD_IMAGE_HASH_SIZE 2048
static struct list_head opd_images[OPD_IMAGE_HASH_SIZE];
void opd_init_images(void)
{
int i;
for (i = 0; i < OPD_IMAGE_HASH_SIZE; ++i) {
list_init(&opd_images[i]);
}
}
int opd_get_nr_images(void)
{
return nr_images;
}
void opd_delete_image(struct opd_image * image)
{
verbprintf(vmisc, "Deleting image: name %s app_name %s, kernel %d, "
"tid %d, tgid %d ref count %u\n",
image->name, image->app_name, image->kernel,
image->tid, image->tgid, (int)image->ref_count);
if (image->ref_count <= 0) {
printf("image->ref_count < 0 for image: name %s app_name %s, "
"kernel %d, tid %d, tgid %d ref count %u\n",
image->name, image->app_name, image->kernel,
image->tid, image->tgid, image->ref_count);
abort();
}
if (--image->ref_count != 0)
return;
if (image->name)
free(image->name);
if (image->app_name)
free(image->app_name);
list_del(&image->hash_next);
opd_close_image_samples_files(image);
free(image);
nr_images--;
}
void opd_for_each_image(opd_image_cb image_cb)
{
struct list_head * pos;
struct list_head * pos2;
int i;
for (i = 0; i < OPD_IMAGE_HASH_SIZE; ++i) {
list_for_each_safe(pos, pos2, &opd_images[i]) {
struct opd_image * image =
list_entry(pos, struct opd_image, hash_next);
image_cb(image);
}
}
}
/**
* opd_hash_image - hash an image
* @param hash hash of image name
* @param tid thread id
* @param tgid thread group id
*
* return the hash code for the passed parameters
*/
static size_t opd_hash_image(char const * name, pid_t tid, pid_t tgid)
{
size_t hash = op_hash_string(name);
if (separate_thread)
hash += tid + tgid;
return hash % OPD_IMAGE_HASH_SIZE;
}
/**
* opd_new_image - create an image sample file
* @param app_name the application name where belongs this image
* @param name name of the image to add
* @param kernel is the image a kernel/module image
* @param tid thread id
* @param tgid thread group id
*
* image at funtion entry is uninitialised
* name is copied i.e. should be GC'd separately from the
* image structure if appropriate.
*
* Initialise an opd_image struct for the image image
* without opening the associated samples files. At return
* the image is fully initialized.
*/
static struct opd_image *
opd_new_image(char const * name, char const * app_name, int kernel,
pid_t tid, pid_t tgid)
{
size_t hash_image;
struct opd_image * image;
verbprintf(vmisc, "Creating image: %s %s, kernel %d, tid %d, "
"tgid %d\n", name, app_name, kernel, tid, tgid);
image = xmalloc(sizeof(struct opd_image));
list_init(&image->hash_next);
image->name = xstrdup(name);
image->kernel = kernel;
image->tid = tid;
image->tgid = tgid;
image->ref_count = 0;
image->app_name = app_name ? xstrdup(app_name) : NULL;
image->mtime = op_get_mtime(image->name);
image->ignored = 1;
if (separate_lib && app_name)
image->ignored = is_image_ignored(app_name);
if (image->ignored)
image->ignored = is_image_ignored(name);
memset(image->sfiles, '\0', NR_CPUS * sizeof(struct opd_24_sfile **));
hash_image = opd_hash_image(name, tid, tgid);
list_add(&image->hash_next, &opd_images[hash_image]);
nr_images++;
return image;
}
/**
* is_same_image - check for identical image
* @param image image to compare
* @param name name of image
* @param app_name image must belong to this application name
* @param tid thread id
* @param tgid thread group id
*
* on entry caller have checked than strcmp(image->name, name) == 0
* return 0 if the couple (name, app_name) refers to same image
*/
static int is_same_image(struct opd_image const * image, char const * app_name,
pid_t tid, pid_t tgid)
{
/* correctness is really important here, if we fail to recognize
* identical image we will open/mmap multiple time the same samples
* files which is not supported by the kernel, strange assertion
* failure in libfd is a typical symptom of that */
if (separate_thread) {
if (image->tid != tid || image->tgid != tgid)
return 1;
}
/* if !separate_lib, the comparison made by caller is enough */
if (!separate_lib)
return 0;
if (image->app_name == NULL && app_name == NULL)
return 0;
if (image->app_name != NULL && app_name != NULL &&
!strcmp(image->app_name, app_name))
return 0;
/* /proc parsed image come with a non null app_name but notification
* for application itself come with a null app_name, in this case
* the test above fail so check for this case. */
if (image->app_name && !app_name && !strcmp(image->app_name, image->name))
return 0;
return 1;
}
/**
* opd_find_image - find an image
* @param name name of image to find
* @param hash hash of image to find
* @param app_name the application name where belongs this image
* @param tid thread id
* @param tgid thread group id
*
* Returns the image pointer for the file specified by name, or %NULL.
*/
static struct opd_image * opd_find_image(char const * name,
char const * app_name, pid_t tid, pid_t tgid)
{
/* suppress uninitialized use warning */
struct opd_image * image = 0;
struct list_head * pos;
size_t bucket;
opd_24_stats[OPD_IMAGE_HASH_ACCESS]++;
bucket = opd_hash_image(name, tid, tgid);
list_for_each(pos, &opd_images[bucket]) {
opd_24_stats[OPD_IMAGE_HASH_DEPTH]++;
image = list_entry(pos, struct opd_image, hash_next);
if (!strcmp(image->name, name)) {
if (!is_same_image(image, app_name, tid, tgid))
break;
}
}
if (pos == &opd_images[bucket])
return NULL;
/* The app_name field is always valid */
return image;
}
struct opd_image * opd_get_image(char const * name, char const * app_name,
int kernel, pid_t tid, pid_t tgid)
{
struct opd_image * image;
if ((image = opd_find_image(name, app_name, tid, tgid)) == NULL)
image = opd_new_image(name, app_name, kernel, tid, tgid);
return image;
}
struct opd_image * opd_get_kernel_image(char const * name,
char const * app_name, pid_t tid, pid_t tgid)
{
return opd_get_image(name, app_name, 1, tid, tgid);
}