init.c
Go to the documentation of this file.00001
00016 #include "config.h"
00017
00018 #include "oprofiled.h"
00019 #include "opd_stats.h"
00020 #include "opd_sfile.h"
00021 #include "opd_pipe.h"
00022 #include "opd_kernel.h"
00023 #include "opd_trans.h"
00024 #include "opd_anon.h"
00025 #include "opd_perfmon.h"
00026 #include "opd_printf.h"
00027 #include "opd_extended.h"
00028
00029 #include "op_version.h"
00030 #include "op_config.h"
00031 #include "op_deviceio.h"
00032 #include "op_get_time.h"
00033 #include "op_libiberty.h"
00034 #include "op_fileio.h"
00035
00036 #include <fcntl.h>
00037 #include <stdio.h>
00038 #include <errno.h>
00039 #include <limits.h>
00040 #include <stdlib.h>
00041 #include <sys/time.h>
00042 #include <wait.h>
00043 #include <string.h>
00044
00045 size_t kernel_pointer_size;
00046
00047 static fd_t devfd;
00048 static char * sbuf;
00049 static size_t s_buf_bytesize;
00050 extern char * session_dir;
00051 static char start_time_str[32];
00052 static int jit_conversion_running;
00053
00054 static void opd_sighup(void);
00055 static void opd_alarm(void);
00056 static void opd_sigterm(void);
00057 static void opd_sigchild(void);
00058 static void opd_do_jitdumps(void);
00059
00066 static void opd_open_files(void)
00067 {
00068 devfd = op_open_device("/dev/oprofile/buffer");
00069 if (devfd == -1) {
00070 if (errno == EINVAL)
00071 fprintf(stderr, "Failed to open device. Possibly you have passed incorrect\n"
00072 "parameters. Check /var/log/messages.");
00073 else
00074 perror("Failed to open profile device");
00075 exit(EXIT_FAILURE);
00076 }
00077
00078
00079 printf("Using log file %s\n", op_log_file);
00080
00081
00082 close(0);
00083 close(1);
00084
00085 if (open("/dev/null", O_RDONLY) == -1) {
00086 perror("oprofiled: couldn't re-open stdin as /dev/null: ");
00087 exit(EXIT_FAILURE);
00088 }
00089
00090 opd_open_logfile();
00091 opd_create_pipe();
00092
00093 printf("oprofiled started %s", op_get_time());
00094 printf("kernel pointer size: %lu\n",
00095 (unsigned long)kernel_pointer_size);
00096 fflush(stdout);
00097 }
00098
00099
00101 static void complete_dump(void)
00102 {
00103 FILE * status_file;
00104
00105 retry:
00106 status_file = fopen(op_dump_status, "w");
00107
00108 if (!status_file && errno == EMFILE) {
00109 if (sfile_lru_clear()) {
00110 printf("LRU cleared but file open fails for %s.\n",
00111 op_dump_status);
00112 abort();
00113 }
00114 goto retry;
00115 }
00116
00117 if (!status_file) {
00118 perror("warning: couldn't set complete_dump: ");
00119 return;
00120 }
00121
00122 fprintf(status_file, "1\n");
00123 fclose(status_file);
00124 }
00125
00126
00136 static void opd_do_samples(char const * opd_buf, ssize_t count)
00137 {
00138 size_t num = count / kernel_pointer_size;
00139
00140 opd_stats[OPD_DUMP_COUNT]++;
00141
00142 verbprintf(vmisc, "Read buffer of %d entries.\n", (unsigned int)num);
00143
00144 opd_process_samples(opd_buf, num);
00145
00146 complete_dump();
00147 }
00148
00149 static void opd_do_jitdumps(void)
00150 {
00151 pid_t childpid;
00152 int arg_num;
00153 unsigned long long end_time = 0ULL;
00154 struct timeval tv;
00155 char end_time_str[32];
00156 char opjitconv_path[PATH_MAX + 1];
00157 char * exec_args[6];
00158
00159 if (jit_conversion_running)
00160 return;
00161 jit_conversion_running = 1;
00162
00163 childpid = fork();
00164 switch (childpid) {
00165 case -1:
00166 perror("Error forking JIT dump process!");
00167 break;
00168 case 0:
00169 gettimeofday(&tv, NULL);
00170 end_time = tv.tv_sec;
00171 sprintf(end_time_str, "%llu", end_time);
00172 sprintf(opjitconv_path, "%s/%s", OP_BINDIR, "opjitconv");
00173 arg_num = 0;
00174 exec_args[arg_num++] = "opjitconv";
00175 if (vmisc)
00176 exec_args[arg_num++] = "-d";
00177 exec_args[arg_num++] = session_dir;
00178 exec_args[arg_num++] = start_time_str;
00179 exec_args[arg_num++] = end_time_str;
00180 exec_args[arg_num] = (char *) NULL;
00181 execvp(opjitconv_path, exec_args);
00182 fprintf(stderr, "Failed to exec %s: %s\n",
00183 exec_args[0], strerror(errno));
00184
00185 _exit(EXIT_FAILURE);
00186 default:
00187 break;
00188 }
00189
00190 }
00191
00200 static void opd_do_read(char * buf, size_t size)
00201 {
00202 opd_open_pipe();
00203
00204 while (1) {
00205 ssize_t count = -1;
00206
00207
00208 while (count < 0) {
00209 count = op_read_device(devfd, buf, size);
00210
00211
00212
00213
00214 if (signal_alarm) {
00215 signal_alarm = 0;
00216 opd_alarm();
00217 }
00218
00219 if (signal_hup) {
00220 signal_hup = 0;
00221 opd_sighup();
00222 }
00223
00224 if (signal_term)
00225 opd_sigterm();
00226
00227 if (signal_child)
00228 opd_sigchild();
00229
00230 if (signal_usr1) {
00231 signal_usr1 = 0;
00232 perfmon_start();
00233 }
00234
00235 if (signal_usr2) {
00236 signal_usr2 = 0;
00237 perfmon_stop();
00238 }
00239
00240 if (is_jitconv_requested()) {
00241 verbprintf(vmisc, "Start opjitconv was triggered\n");
00242 opd_do_jitdumps();
00243 }
00244 }
00245
00246 opd_do_samples(buf, count);
00247 }
00248
00249 opd_close_pipe();
00250 }
00251
00252
00254 static void opd_alarm(void)
00255 {
00256 sfile_sync_files();
00257 opd_print_stats();
00258 alarm(60 * 10);
00259 }
00260
00261
00263 static void opd_sighup(void)
00264 {
00265 printf("Received SIGHUP.\n");
00266
00267 sfile_close_files();
00268 close(1);
00269 close(2);
00270 opd_open_logfile();
00271 }
00272
00273
00274 static void clean_exit(void)
00275 {
00276 perfmon_exit();
00277 unlink(op_lock_file);
00278 }
00279
00280
00281 static void opd_sigterm(void)
00282 {
00283 opd_do_jitdumps();
00284 opd_print_stats();
00285 printf("oprofiled stopped %s", op_get_time());
00286 opd_ext_deinitialize();
00287
00288 exit(EXIT_FAILURE);
00289 }
00290
00291
00292 static void opd_sigchild(void)
00293 {
00294 int child_status;
00295 wait(&child_status);
00296 jit_conversion_running = 0;
00297 if (WIFEXITED(child_status) && (!WEXITSTATUS(child_status))) {
00298 verbprintf(vmisc, "JIT dump processing complete.\n");
00299 } else {
00300 printf("JIT dump processing exited abnormally: %d\n",
00301 WEXITSTATUS(child_status));
00302 }
00303
00304 }
00305
00306 static void opd_26_init(void)
00307 {
00308 size_t i;
00309 size_t opd_buf_size;
00310 unsigned long long start_time = 0ULL;
00311 struct timeval tv;
00312
00313 opd_create_vmlinux(vmlinux, kernel_range);
00314 opd_create_xen(xenimage, xen_range);
00315
00316 opd_buf_size = opd_read_fs_int("/dev/oprofile/", "buffer_size", 1);
00317 kernel_pointer_size = opd_read_fs_int("/dev/oprofile/", "pointer_size", 1);
00318
00319 s_buf_bytesize = opd_buf_size * kernel_pointer_size;
00320
00321 sbuf = xmalloc(s_buf_bytesize);
00322
00323 opd_reread_module_info();
00324
00325 for (i = 0; i < OPD_MAX_STATS; i++)
00326 opd_stats[i] = 0;
00327
00328 perfmon_init();
00329
00330 cookie_init();
00331 sfile_init();
00332 anon_init();
00333
00334
00335 if (atexit(clean_exit)) {
00336 perfmon_exit();
00337 perror("oprofiled: couldn't set exit cleanup: ");
00338 exit(EXIT_FAILURE);
00339 }
00340
00341
00342 opd_open_files();
00343 gettimeofday(&tv, NULL);
00344 start_time = 0ULL;
00345 start_time = tv.tv_sec;
00346 sprintf(start_time_str, "%llu", start_time);
00347
00348 }
00349
00350
00351 static void opd_26_start(void)
00352 {
00353
00354 opd_do_read(sbuf, s_buf_bytesize);
00355 }
00356
00357
00358 static void opd_26_exit(void)
00359 {
00360 opd_print_stats();
00361 printf("oprofiled stopped %s", op_get_time());
00362
00363 free(sbuf);
00364 free(vmlinux);
00365
00366 }
00367
00368 struct oprofiled_ops opd_26_ops = {
00369 .init = opd_26_init,
00370 .start = opd_26_start,
00371 .exit = opd_26_exit,
00372 };