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     /* give output before re-opening stdout as the logfile */
00079     printf("Using log file %s\n", op_log_file);
00080 
00081     /* set up logfile */
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             /* We don't want any cleanup in the child */
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         /* loop to handle EINTR */
00208         while (count < 0) {
00209             count = op_read_device(devfd, buf, size);
00210 
00211             /* we can lose an alarm or a hup but
00212              * we don't care.
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     /* We just close them, and re-open them lazily as usual. */
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 /* SIGCHLD received from JIT dump child process. */
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     /* must be /after/ perfmon_init() at least */
00335     if (atexit(clean_exit)) {
00336         perfmon_exit();
00337         perror("oprofiled: couldn't set exit cleanup: ");
00338         exit(EXIT_FAILURE);
00339     }
00340 
00341     /* trigger kernel module setup before returning control to opcontrol */
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     /* simple sleep-then-process loop */
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     /* FIXME: free kernel images, sfiles etc. */
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 };

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1