init.c

Go to the documentation of this file.
00001 
00012 #include "config.h"
00013  
00014 #include "opd_proc.h"
00015 #include "opd_mapping.h"
00016 #include "opd_24_stats.h"
00017 #include "opd_sample_files.h"
00018 #include "opd_image.h"
00019 #include "opd_parse_proc.h"
00020 #include "opd_kernel.h"
00021 #include "opd_printf.h"
00022 #include "oprofiled.h"
00023 
00024 #include "op_sample_file.h"
00025 #include "op_config_24.h"
00026 #include "op_interface.h"
00027 #include "op_libiberty.h"
00028 #include "op_deviceio.h"
00029 #include "op_events.h"
00030 #include "op_get_time.h"
00031 #include "op_fileio.h"
00032 
00033 #include <stdio.h>
00034 #include <errno.h>
00035 #include <fcntl.h>
00036 #include <unistd.h>
00037 #include <stdlib.h>
00038 
00039 fd_t hashmapdevfd;
00040 
00041 int cpu_number;
00042 
00043 static fd_t devfd;
00044 static fd_t notedevfd;
00045 static struct op_buffer_head * sbuf;
00046 static size_t s_buf_bytesize;
00047 static struct op_note * nbuf;
00048 static size_t n_buf_bytesize;
00049 
00050 static void opd_sighup(void);
00051 static void opd_alarm(void);
00052 static void opd_sigterm(void);
00053 
00054 
00061 static void op_open_files(void)
00062 {
00063     hashmapdevfd = op_open_device(op_hash_device);
00064     if (hashmapdevfd == -1) {
00065         perror("Failed to open hash map device");
00066         exit(EXIT_FAILURE);
00067     }
00068 
00069     notedevfd = op_open_device(op_note_device);
00070     if (notedevfd == -1) {
00071         if (errno == EINVAL)
00072             fprintf(stderr, "Failed to open note device. Possibly you have passed incorrect\n"
00073                 "parameters. Check /var/log/messages.");
00074         else
00075             perror("Failed to open note device");
00076         exit(EXIT_FAILURE);
00077     }
00078 
00079     devfd = op_open_device(op_device);
00080     if (devfd == -1) {
00081         if (errno == EINVAL)
00082             fprintf(stderr, "Failed to open device. Possibly you have passed incorrect\n"
00083                 "parameters. Check /var/log/messages.");
00084         else
00085             perror("Failed to open profile device");
00086         exit(EXIT_FAILURE);
00087     }
00088 
00089     opd_init_hash_map();
00090 
00091     /* give output before re-opening stdout as the logfile */
00092     printf("Using log file %s\n", op_log_file);
00093 
00094     /* set up logfile */
00095     close(0);
00096     close(1);
00097 
00098     if (open("/dev/null", O_RDONLY) == -1) {
00099         perror("oprofiled: couldn't re-open stdin as /dev/null: ");
00100         exit(EXIT_FAILURE);
00101     }
00102 
00103     opd_open_logfile();
00104 
00105     printf("oprofiled started %s", op_get_time());
00106     fflush(stdout);
00107 }
00108  
00109 
00110 static void opd_do_samples(struct op_buffer_head const * buf);
00111 static void opd_do_notes(struct op_note const * opd_buf, size_t count);
00112 
00120 static void opd_shutdown(struct op_buffer_head * buf, size_t size, struct op_note * nbuf, size_t nsize)
00121 {
00122     ssize_t count = -1;
00123     ssize_t ncount = -1;
00124 
00125     /* the dump may have added no samples, so we must set
00126      * non-blocking */
00127     if (fcntl(devfd, F_SETFL, fcntl(devfd, F_GETFL) | O_NONBLOCK) < 0) {
00128         perror("Failed to set non-blocking read for device: ");
00129         exit(EXIT_FAILURE);
00130     }
00131 
00132     /* it's always OK to read the note device */
00133     while (ncount < 0)
00134         ncount = op_read_device(notedevfd, nbuf, nsize);
00135 
00136     if (ncount > 0)
00137         opd_do_notes(nbuf, ncount);
00138 
00139     /* read as much as we can until we have exhausted the data
00140      * (EAGAIN is returned).
00141      *
00142      * This will not livelock as the profiler has been partially
00143      * shut down by now.
00144      */
00145     while (1) {
00146         count = op_read_device(devfd, buf, size);
00147         if (count < 0 && errno == EAGAIN)
00148             break;
00149         verbprintf(vmisc, "Shutting down, state %d\n", buf->state);
00150         opd_do_samples(buf);
00151     }
00152 }
00153  
00154 
00165 static void opd_do_read(struct op_buffer_head * buf, size_t size, struct op_note * nbuf, size_t nsize)
00166 {
00167     while (1) {
00168         ssize_t count = -1;
00169         ssize_t ncount = -1;
00170 
00171         /* loop to handle EINTR */
00172         while (count < 0)
00173             count = op_read_device(devfd, buf, size);
00174 
00175         while (ncount < 0)
00176             ncount = op_read_device(notedevfd, nbuf, nsize);
00177 
00178         opd_do_notes(nbuf, ncount);
00179         opd_do_samples(buf);
00180 
00181         // we can lost a signal alarm or a signal hup but we don't
00182         // take care.
00183         if (signal_alarm) {
00184             signal_alarm = 0;
00185             opd_alarm();
00186         }
00187 
00188         if (signal_hup) {
00189             signal_hup = 0;
00190             opd_sighup();
00191         }
00192 
00193         if (signal_term)
00194             opd_sigterm();
00195  
00196         /* request to stop arrived */
00197         if (buf->state == STOPPING) {
00198             verbprintf(vmisc, "Shutting down by request.\n");
00199             opd_shutdown(buf, size, nbuf, nsize);
00200             return;
00201         }
00202     }
00203 }
00204 
00212 static void opd_do_notes(struct op_note const * opd_buf, size_t count)
00213 {
00214     uint i;
00215     struct op_note const * note;
00216 
00217     for (i = 0; i < count/sizeof(struct op_note); i++) {
00218         note = &opd_buf[i];
00219 
00220         opd_24_stats[OPD_NOTIFICATIONS]++;
00221 
00222         switch (note->type) {
00223             case OP_MAP:
00224             case OP_EXEC:
00225                 if (note->type == OP_EXEC)
00226                     opd_handle_exec(note->pid, note->tgid);
00227                 opd_handle_mapping(note);
00228                 break;
00229 
00230             case OP_FORK:
00231                 opd_handle_fork(note);
00232                 break;
00233 
00234             case OP_DROP_MODULES:
00235                 opd_clear_module_info();
00236                 break;
00237 
00238             case OP_EXIT:
00239                 opd_handle_exit(note);
00240                 break;
00241 
00242             default:
00243                 fprintf(stderr, "Received unknown notification type %u\n", note->type);
00244                 abort();
00245                 break;
00246         }
00247     }
00248 }
00249 
00262 static void opd_do_samples(struct op_buffer_head const * opd_buf)
00263 {
00264     uint i;
00265     struct op_sample const * buffer = opd_buf->buffer; 
00266 
00267     opd_24_stats[OPD_DUMP_COUNT]++;
00268 
00269     verbprintf(vmisc, "Read buffer of %d entries for cpu %d.\n",
00270            (unsigned int)opd_buf->count, opd_buf->cpu_nr);
00271  
00272     if (separate_cpu)
00273         cpu_number = opd_buf->cpu_nr;
00274     for (i = 0; i < opd_buf->count; i++) {
00275         verbprintf(vsamples, "%.6u: EIP: 0x%.8lx pid: %.6d\n",
00276             i, buffer[i].eip, buffer[i].pid);
00277         opd_put_sample(&buffer[i]);
00278     }
00279 }
00280 
00281 
00285 static void opd_alarm(void)
00286 {
00287     opd_sync_samples_files();
00288 
00289     opd_age_procs();
00290 
00291     opd_print_24_stats();
00292 
00293     alarm(60 * 10);
00294 }
00295  
00296 
00297 /* re-open logfile for logrotate */
00298 static void opd_sighup(void)
00299 {
00300     printf("Received SIGHUP.\n");
00301     close(1);
00302     close(2);
00303     opd_open_logfile();
00304     /* We just close them, and re-open them lazily as usual. */
00305     opd_for_each_image(opd_close_image_samples_files);
00306 }
00307 
00308 
00309 static void clean_exit(void)
00310 {
00311     opd_cleanup_hash_name();
00312     op_free_events();
00313     unlink(op_lock_file);
00314 }
00315 
00316 
00317 static void opd_sigterm(void)
00318 {
00319     opd_print_24_stats();
00320     printf("oprofiled stopped %s", op_get_time());
00321     exit(EXIT_FAILURE);
00322 }
00323  
00324 
00325 static void opd_24_init(void)
00326 {
00327     size_t i;
00328     int opd_buf_size = OP_DEFAULT_BUF_SIZE;
00329     int opd_note_buf_size = OP_DEFAULT_NOTE_SIZE;
00330 
00331     if (!no_vmlinux)
00332         opd_parse_kernel_range(kernel_range);
00333     opd_buf_size = opd_read_fs_int(OP_MOUNT, "bufsize", 1);
00334     opd_note_buf_size = opd_read_fs_int(OP_MOUNT, "notesize", 1);
00335 
00336     s_buf_bytesize = sizeof(struct op_buffer_head) + opd_buf_size * sizeof(struct op_sample);
00337 
00338     sbuf = xmalloc(s_buf_bytesize);
00339 
00340     n_buf_bytesize = opd_note_buf_size * sizeof(struct op_note);
00341     nbuf = xmalloc(n_buf_bytesize);
00342 
00343     opd_init_images();
00344     opd_init_procs();
00345     opd_init_kernel_image();
00346 
00347     for (i = 0; i < OPD_MAX_STATS; i++)
00348         opd_24_stats[i] = 0;
00349 
00350     if (atexit(clean_exit)) {
00351         perror("oprofiled: couldn't set exit cleanup: ");
00352         exit(EXIT_FAILURE);
00353     }
00354 }
00355 
00356 
00357 static void opd_24_start(void)
00358 {
00359     op_open_files();
00360 
00361     /* yes, this is racey. */
00362     opd_get_ascii_procs();
00363 
00364     /* simple sleep-then-process loop */
00365     opd_do_read(sbuf, s_buf_bytesize, nbuf, n_buf_bytesize);
00366 }
00367 
00368 
00369 static void opd_24_exit(void)
00370 {
00371     opd_print_24_stats();
00372     printf("oprofiled stopped %s", op_get_time());
00373 
00374     free(sbuf);
00375     free(nbuf);
00376     opd_clear_module_info();
00377     opd_proc_cleanup();
00378     /* kernel/module image are not owned by a proc, we must cleanup them */
00379     opd_for_each_image(opd_delete_image);
00380 }
00381 
00382 
00383 struct oprofiled_ops opd_24_ops = {
00384     .init = opd_24_init,
00385     .start = opd_24_start,
00386     .exit = opd_24_exit
00387 };

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1