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