00001
00012 #include "opd_image.h"
00013 #include "opd_printf.h"
00014 #include "opd_sample_files.h"
00015 #include "opd_24_stats.h"
00016 #include "oprofiled.h"
00017
00018 #include "op_file.h"
00019 #include "op_config_24.h"
00020 #include "op_libiberty.h"
00021 #include "op_string.h"
00022
00023 #include <string.h>
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026
00027
00028 static int nr_images;
00029
00030
00031 #define OPD_IMAGE_HASH_SIZE 2048
00032 static struct list_head opd_images[OPD_IMAGE_HASH_SIZE];
00033
00034
00035 void opd_init_images(void)
00036 {
00037 int i;
00038 for (i = 0; i < OPD_IMAGE_HASH_SIZE; ++i)
00039 list_init(&opd_images[i]);
00040 }
00041
00042
00043 int opd_get_nr_images(void)
00044 {
00045 return nr_images;
00046 }
00047
00048
00049 void opd_delete_image(struct opd_image * image)
00050 {
00051 verbprintf(vmisc, "Deleting image: name %s app_name %s, kernel %d, "
00052 "tid %d, tgid %d ref count %u\n",
00053 image->name, image->app_name, image->kernel,
00054 image->tid, image->tgid, (int)image->ref_count);
00055
00056 if (image->ref_count <= 0) {
00057 printf("image->ref_count < 0 for image: name %s app_name %s, "
00058 "kernel %d, tid %d, tgid %d ref count %u\n",
00059 image->name, image->app_name, image->kernel,
00060 image->tid, image->tgid, image->ref_count);
00061 abort();
00062 }
00063
00064 if (--image->ref_count != 0)
00065 return;
00066
00067 if (image->name)
00068 free(image->name);
00069 if (image->app_name)
00070 free(image->app_name);
00071 list_del(&image->hash_next);
00072 opd_close_image_samples_files(image);
00073 free(image);
00074
00075 nr_images--;
00076 }
00077
00078
00079 void opd_for_each_image(opd_image_cb image_cb)
00080 {
00081 struct list_head * pos;
00082 struct list_head * pos2;
00083 int i;
00084
00085 for (i = 0; i < OPD_IMAGE_HASH_SIZE; ++i) {
00086 list_for_each_safe(pos, pos2, &opd_images[i]) {
00087 struct opd_image * image =
00088 list_entry(pos, struct opd_image, hash_next);
00089 image_cb(image);
00090 }
00091 }
00092 }
00093
00094
00103 static size_t opd_hash_image(char const * name, pid_t tid, pid_t tgid)
00104 {
00105 size_t hash = op_hash_string(name);
00106 if (separate_thread)
00107 hash += tid + tgid;
00108 return hash % OPD_IMAGE_HASH_SIZE;
00109 }
00110
00111
00128 static struct opd_image *
00129 opd_new_image(char const * name, char const * app_name, int kernel,
00130 pid_t tid, pid_t tgid)
00131 {
00132 size_t hash_image;
00133 struct opd_image * image;
00134
00135 verbprintf(vmisc, "Creating image: %s %s, kernel %d, tid %d, "
00136 "tgid %d\n", name, app_name, kernel, tid, tgid);
00137
00138 image = xmalloc(sizeof(struct opd_image));
00139
00140 list_init(&image->hash_next);
00141 image->name = xstrdup(name);
00142 image->kernel = kernel;
00143 image->tid = tid;
00144 image->tgid = tgid;
00145 image->ref_count = 0;
00146 image->app_name = app_name ? xstrdup(app_name) : NULL;
00147 image->mtime = op_get_mtime(image->name);
00148
00149 image->ignored = 1;
00150 if (separate_lib && app_name)
00151 image->ignored = is_image_ignored(app_name);
00152 if (image->ignored)
00153 image->ignored = is_image_ignored(name);
00154
00155 memset(image->sfiles, '\0', NR_CPUS * sizeof(struct opd_24_sfile **));
00156
00157 hash_image = opd_hash_image(name, tid, tgid);
00158 list_add(&image->hash_next, &opd_images[hash_image]);
00159
00160 nr_images++;
00161
00162 return image;
00163 }
00164
00165
00177 static int is_same_image(struct opd_image const * image, char const * app_name,
00178 pid_t tid, pid_t tgid)
00179 {
00180
00181
00182
00183
00184
00185 if (separate_thread) {
00186 if (image->tid != tid || image->tgid != tgid)
00187 return 1;
00188 }
00189
00190
00191 if (!separate_lib)
00192 return 0;
00193
00194 if (image->app_name == NULL && app_name == NULL)
00195 return 0;
00196
00197 if (image->app_name != NULL && app_name != NULL &&
00198 !strcmp(image->app_name, app_name))
00199 return 0;
00200
00201
00202
00203
00204 if (image->app_name && !app_name && !strcmp(image->app_name, image->name))
00205 return 0;
00206
00207 return 1;
00208 }
00209
00210
00221 static struct opd_image * opd_find_image(char const * name,
00222 char const * app_name, pid_t tid, pid_t tgid)
00223 {
00224
00225 struct opd_image * image = 0;
00226 struct list_head * pos;
00227 size_t bucket;
00228
00229 opd_24_stats[OPD_IMAGE_HASH_ACCESS]++;
00230 bucket = opd_hash_image(name, tid, tgid);
00231 list_for_each(pos, &opd_images[bucket]) {
00232 opd_24_stats[OPD_IMAGE_HASH_DEPTH]++;
00233 image = list_entry(pos, struct opd_image, hash_next);
00234
00235 if (!strcmp(image->name, name)) {
00236 if (!is_same_image(image, app_name, tid, tgid))
00237 break;
00238 }
00239 }
00240
00241 if (pos == &opd_images[bucket])
00242 return NULL;
00243
00244
00245 return image;
00246 }
00247
00248
00249 struct opd_image * opd_get_image(char const * name, char const * app_name,
00250 int kernel, pid_t tid, pid_t tgid)
00251 {
00252 struct opd_image * image;
00253 if ((image = opd_find_image(name, app_name, tid, tgid)) == NULL)
00254 image = opd_new_image(name, app_name, kernel, tid, tgid);
00255
00256 return image;
00257 }
00258
00259
00260 struct opd_image * opd_get_kernel_image(char const * name,
00261 char const * app_name, pid_t tid, pid_t tgid)
00262 {
00263 return opd_get_image(name, app_name, 1, tid, tgid);
00264 }