18cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/** 28cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @file daemon/liblegacy/init.c 38cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Daemon set up and main loop for 2.4 48cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 58cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Copyright 2002 OProfile authors 68cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Read the file COPYING 78cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 88cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author John Levon 98cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Philippe Elie 108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "config.h" 138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_proc.h" 158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_mapping.h" 168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_24_stats.h" 178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_sample_files.h" 188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_image.h" 198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_parse_proc.h" 208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_kernel.h" 218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_printf.h" 228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "oprofiled.h" 238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_sample_file.h" 258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_config_24.h" 268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_interface.h" 278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_libiberty.h" 288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_deviceio.h" 298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_events.h" 308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_get_time.h" 318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_fileio.h" 328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <stdio.h> 348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <errno.h> 358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <fcntl.h> 368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <unistd.h> 378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <stdlib.h> 388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddfd_t hashmapdevfd; 408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddint cpu_number; 428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic fd_t devfd; 448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic fd_t notedevfd; 458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic struct op_buffer_head * sbuf; 468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic size_t s_buf_bytesize; 478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic struct op_note * nbuf; 488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic size_t n_buf_bytesize; 498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_sighup(void); 518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_alarm(void); 528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_sigterm(void); 538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/** 568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * op_open_files - open necessary files 578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Open the device files and the log file, 598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * and mmap() the hash map. 608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void op_open_files(void) 628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd hashmapdevfd = op_open_device(op_hash_device); 648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (hashmapdevfd == -1) { 658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd perror("Failed to open hash map device"); 668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd exit(EXIT_FAILURE); 678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd notedevfd = op_open_device(op_note_device); 708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (notedevfd == -1) { 718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (errno == EINVAL) 728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd fprintf(stderr, "Failed to open note device. Possibly you have passed incorrect\n" 738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd "parameters. Check /var/log/messages."); 748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd else 758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd perror("Failed to open note device"); 768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd exit(EXIT_FAILURE); 778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd devfd = op_open_device(op_device); 808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (devfd == -1) { 818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (errno == EINVAL) 828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd fprintf(stderr, "Failed to open device. Possibly you have passed incorrect\n" 838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd "parameters. Check /var/log/messages."); 848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd else 858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd perror("Failed to open profile device"); 868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd exit(EXIT_FAILURE); 878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_init_hash_map(); 908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* give output before re-opening stdout as the logfile */ 928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd printf("Using log file %s\n", op_log_file); 938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* set up logfile */ 958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd close(0); 968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd close(1); 978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (open("/dev/null", O_RDONLY) == -1) { 998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd perror("oprofiled: couldn't re-open stdin as /dev/null: "); 1008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd exit(EXIT_FAILURE); 1018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_open_logfile(); 1048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd printf("oprofiled started %s", op_get_time()); 1068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd fflush(stdout); 1078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 1088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_do_samples(struct op_buffer_head const * buf); 1118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_do_notes(struct op_note const * opd_buf, size_t count); 1128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/** 1148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * do_shutdown - shutdown cleanly, reading as much remaining data as possible. 1158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param buf sample buffer area 1168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param size size of sample buffer 1178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param nbuf note buffer area 1188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param nsize size of note buffer 1198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 1208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_shutdown(struct op_buffer_head * buf, size_t size, struct op_note * nbuf, size_t nsize) 1218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 1228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ssize_t count = -1; 1238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ssize_t ncount = -1; 1248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* the dump may have added no samples, so we must set 1268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * non-blocking */ 1278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (fcntl(devfd, F_SETFL, fcntl(devfd, F_GETFL) | O_NONBLOCK) < 0) { 1288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd perror("Failed to set non-blocking read for device: "); 1298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd exit(EXIT_FAILURE); 1308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* it's always OK to read the note device */ 1338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd while (ncount < 0) 1348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ncount = op_read_device(notedevfd, nbuf, nsize); 1358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (ncount > 0) 1378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_do_notes(nbuf, ncount); 1388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* read as much as we can until we have exhausted the data 1408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * (EAGAIN is returned). 1418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 1428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * This will not livelock as the profiler has been partially 1438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * shut down by now. 1448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 1458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd while (1) { 1468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd count = op_read_device(devfd, buf, size); 1478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (count < 0 && errno == EAGAIN) 1488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd break; 1498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd verbprintf(vmisc, "Shutting down, state %d\n", buf->state); 1508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_do_samples(buf); 1518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 1538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/** 1568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * opd_do_read - enter processing loop 1578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param buf buffer to read into 1588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param size size of buffer 1598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param nbuf note buffer 1608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param nsize size of note buffer 1618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 1628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Read some of a buffer from the device and process 1638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * the contents. 1648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 1658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_do_read(struct op_buffer_head * buf, size_t size, struct op_note * nbuf, size_t nsize) 1668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 1678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd while (1) { 1688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ssize_t count = -1; 1698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ssize_t ncount = -1; 1708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* loop to handle EINTR */ 1728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd while (count < 0) 1738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd count = op_read_device(devfd, buf, size); 1748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd while (ncount < 0) 1768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ncount = op_read_device(notedevfd, nbuf, nsize); 1778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_do_notes(nbuf, ncount); 1798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_do_samples(buf); 1808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // we can lost a signal alarm or a signal hup but we don't 1828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // take care. 1838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (signal_alarm) { 1848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd signal_alarm = 0; 1858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_alarm(); 1868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (signal_hup) { 1898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd signal_hup = 0; 1908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_sighup(); 1918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (signal_term) 1948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_sigterm(); 1958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* request to stop arrived */ 1978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (buf->state == STOPPING) { 1988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd verbprintf(vmisc, "Shutting down by request.\n"); 1998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_shutdown(buf, size, nbuf, nsize); 2008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return; 2018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/** 2068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * opd_do_notes - process a notes buffer 2078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param opd_buf buffer to process 2088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param count number of bytes in buffer 2098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 2108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Process a buffer of notes. 2118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 2128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_do_notes(struct op_note const * opd_buf, size_t count) 2138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 2148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd uint i; 2158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd struct op_note const * note; 2168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (i = 0; i < count/sizeof(struct op_note); i++) { 2188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd note = &opd_buf[i]; 2198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_24_stats[OPD_NOTIFICATIONS]++; 2218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd switch (note->type) { 2238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd case OP_MAP: 2248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd case OP_EXEC: 2258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (note->type == OP_EXEC) 2268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_handle_exec(note->pid, note->tgid); 2278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_handle_mapping(note); 2288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd break; 2298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd case OP_FORK: 2318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_handle_fork(note); 2328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd break; 2338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd case OP_DROP_MODULES: 2358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_clear_module_info(); 2368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd break; 2378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd case OP_EXIT: 2398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_handle_exit(note); 2408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd break; 2418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd default: 2438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd fprintf(stderr, "Received unknown notification type %u\n", note->type); 2448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd abort(); 2458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd break; 2468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/** 2518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * opd_do_samples - process a sample buffer 2528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param opd_buf buffer to process 2538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 2548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Process a buffer of samples. 2558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * The signals specified by the global variable maskset are 2568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * masked. 2578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 2588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * If the sample could be processed correctly, it is written 2598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * to the relevant sample file. Additionally mapping and 2608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * process notifications are handled here. 2618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 2628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_do_samples(struct op_buffer_head const * opd_buf) 2638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 2648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd uint i; 2658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd struct op_sample const * buffer = opd_buf->buffer; 2668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_24_stats[OPD_DUMP_COUNT]++; 2688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd verbprintf(vmisc, "Read buffer of %d entries for cpu %d.\n", 2708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd (unsigned int)opd_buf->count, opd_buf->cpu_nr); 2718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (separate_cpu) 2738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cpu_number = opd_buf->cpu_nr; 2748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (i = 0; i < opd_buf->count; i++) { 2758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd verbprintf(vsamples, "%.6u: EIP: 0x%.8lx pid: %.6d\n", 2768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd i, buffer[i].eip, buffer[i].pid); 2778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_put_sample(&buffer[i]); 2788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/** 2838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * opd_alarm - clean up old procs, msync, and report stats 2848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 2858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_alarm(void) 2868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 2878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_sync_samples_files(); 2888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_age_procs(); 2908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_print_24_stats(); 2928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd alarm(60 * 10); 2948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* re-open logfile for logrotate */ 2988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_sighup(void) 2998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd printf("Received SIGHUP.\n"); 3018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd close(1); 3028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd close(2); 3038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_open_logfile(); 3048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* We just close them, and re-open them lazily as usual. */ 3058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_for_each_image(opd_close_image_samples_files); 3068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void clean_exit(void) 3108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_cleanup_hash_name(); 3128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd op_free_events(); 3138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd unlink(op_lock_file); 3148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_sigterm(void) 3188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_print_24_stats(); 3208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd printf("oprofiled stopped %s", op_get_time()); 3218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd exit(EXIT_FAILURE); 3228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_24_init(void) 3268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd size_t i; 3288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd int opd_buf_size = OP_DEFAULT_BUF_SIZE; 3298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd int opd_note_buf_size = OP_DEFAULT_NOTE_SIZE; 3308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!no_vmlinux) 3328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_parse_kernel_range(kernel_range); 3338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_buf_size = opd_read_fs_int(OP_MOUNT, "bufsize", 1); 3348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_note_buf_size = opd_read_fs_int(OP_MOUNT, "notesize", 1); 3358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd s_buf_bytesize = sizeof(struct op_buffer_head) + opd_buf_size * sizeof(struct op_sample); 3378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sbuf = xmalloc(s_buf_bytesize); 3398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd n_buf_bytesize = opd_note_buf_size * sizeof(struct op_note); 3418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd nbuf = xmalloc(n_buf_bytesize); 3428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_init_images(); 3448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_init_procs(); 3458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_init_kernel_image(); 3468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (i = 0; i < OPD_MAX_STATS; i++) 3488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_24_stats[i] = 0; 3498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (atexit(clean_exit)) { 3518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd perror("oprofiled: couldn't set exit cleanup: "); 3528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd exit(EXIT_FAILURE); 3538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 3548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_24_start(void) 3588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd op_open_files(); 3608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* yes, this is racey. */ 3628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_get_ascii_procs(); 3638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* simple sleep-then-process loop */ 3658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_do_read(sbuf, s_buf_bytesize, nbuf, n_buf_bytesize); 3668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_24_exit(void) 3708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_print_24_stats(); 3728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd printf("oprofiled stopped %s", op_get_time()); 3738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd free(sbuf); 3758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd free(nbuf); 3768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_clear_module_info(); 3778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_proc_cleanup(); 3788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* kernel/module image are not owned by a proc, we must cleanup them */ 3798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd opd_for_each_image(opd_delete_image); 3808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct oprofiled_ops opd_24_ops = { 3848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd .init = opd_24_init, 3858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd .start = opd_24_start, 3868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd .exit = opd_24_exit 3878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}; 388