3
* Daemon set up and main loop for 2.6
5
* @remark Copyright 2002 OProfile authors
6
* @remark Read the file COPYING
9
* @author Philippe Elie
10
* @Modifications Daniel Hansel
11
* Modified by Aravind Menon for Xen
12
* These modifications are:
13
* Copyright (C) 2005 Hewlett-Packard Co.
18
#include "oprofiled.h"
19
#include "opd_stats.h"
20
#include "opd_sfile.h"
22
#include "opd_kernel.h"
23
#include "opd_trans.h"
25
#include "opd_perfmon.h"
26
#include "opd_printf.h"
27
#include "opd_extended.h"
29
#include "op_version.h"
30
#include "op_config.h"
31
#include "op_deviceio.h"
32
#include "op_get_time.h"
33
#include "op_libiberty.h"
34
#include "op_fileio.h"
45
size_t kernel_pointer_size;
49
static size_t s_buf_bytesize;
50
extern char * session_dir;
51
static char start_time_str[32];
52
static int jit_conversion_running;
54
static void opd_sighup(void);
55
static void opd_alarm(void);
56
static void opd_sigterm(void);
57
static void opd_sigchild(void);
58
static void opd_do_jitdumps(void);
61
* opd_open_files - open necessary files
63
* Open the device files and the log file,
64
* and mmap() the hash map.
66
static void opd_open_files(void)
68
devfd = op_open_device("/dev/oprofile/buffer");
71
fprintf(stderr, "Failed to open device. Possibly you have passed incorrect\n"
72
"parameters. Check /var/log/messages.");
74
perror("Failed to open profile device");
78
/* give output before re-opening stdout as the logfile */
79
printf("Using log file %s\n", op_log_file);
85
if (open("/dev/null", O_RDONLY) == -1) {
86
perror("oprofiled: couldn't re-open stdin as /dev/null: ");
93
printf("oprofiled started %s", op_get_time());
94
printf("kernel pointer size: %lu\n",
95
(unsigned long)kernel_pointer_size);
100
/** Done writing out the samples, indicate with complete_dump file */
101
static void complete_dump(void)
106
status_file = fopen(op_dump_status, "w");
108
if (!status_file && errno == EMFILE) {
109
if (sfile_lru_clear()) {
110
printf("LRU cleared but file open fails for %s.\n",
118
perror("warning: couldn't set complete_dump: ");
122
fprintf(status_file, "1\n");
128
* opd_do_samples - process a sample buffer
129
* @param opd_buf buffer to process
131
* Process a buffer of samples.
133
* If the sample could be processed correctly, it is written
134
* to the relevant sample file.
136
static void opd_do_samples(char const * opd_buf, ssize_t count)
138
size_t num = count / kernel_pointer_size;
140
opd_stats[OPD_DUMP_COUNT]++;
142
verbprintf(vmisc, "Read buffer of %d entries.\n", (unsigned int)num);
144
opd_process_samples(opd_buf, num);
149
static void opd_do_jitdumps(void)
153
unsigned long long end_time = 0ULL;
155
char end_time_str[32];
156
char opjitconv_path[PATH_MAX + 1];
159
if (jit_conversion_running)
161
jit_conversion_running = 1;
166
perror("Error forking JIT dump process!");
169
gettimeofday(&tv, NULL);
170
end_time = tv.tv_sec;
171
sprintf(end_time_str, "%llu", end_time);
172
sprintf(opjitconv_path, "%s/%s", OP_BINDIR, "opjitconv");
174
exec_args[arg_num++] = "opjitconv";
176
exec_args[arg_num++] = "-d";
177
exec_args[arg_num++] = session_dir;
178
exec_args[arg_num++] = start_time_str;
179
exec_args[arg_num++] = end_time_str;
180
exec_args[arg_num] = (char *) NULL;
181
execvp(opjitconv_path, exec_args);
182
fprintf(stderr, "Failed to exec %s: %s\n",
183
exec_args[0], strerror(errno));
184
/* We don't want any cleanup in the child */
193
* opd_do_read - enter processing loop
194
* @param buf buffer to read into
195
* @param size size of buffer
197
* Read some of a buffer from the device and process
200
static void opd_do_read(char * buf, size_t size)
207
/* loop to handle EINTR */
209
count = op_read_device(devfd, buf, size);
211
/* we can lose an alarm or a hup but
240
if (is_jitconv_requested()) {
241
verbprintf(vmisc, "Start opjitconv was triggered\n");
246
opd_do_samples(buf, count);
253
/** opd_alarm - sync files and report stats */
254
static void opd_alarm(void)
262
/** re-open files for logrotate/opcontrol --reset */
263
static void opd_sighup(void)
265
printf("Received SIGHUP.\n");
266
/* We just close them, and re-open them lazily as usual. */
274
static void clean_exit(void)
277
unlink(op_lock_file);
281
static void opd_sigterm(void)
285
printf("oprofiled stopped %s", op_get_time());
286
opd_ext_deinitialize();
291
/* SIGCHLD received from JIT dump child process. */
292
static void opd_sigchild(void)
296
jit_conversion_running = 0;
297
if (WIFEXITED(child_status) && (!WEXITSTATUS(child_status))) {
298
verbprintf(vmisc, "JIT dump processing complete.\n");
300
printf("JIT dump processing exited abnormally: %d\n",
301
WEXITSTATUS(child_status));
306
static void opd_26_init(void)
310
unsigned long long start_time = 0ULL;
313
opd_create_vmlinux(vmlinux, kernel_range);
314
opd_create_xen(xenimage, xen_range);
316
opd_buf_size = opd_read_fs_int("/dev/oprofile/", "buffer_size", 1);
317
kernel_pointer_size = opd_read_fs_int("/dev/oprofile/", "pointer_size", 1);
319
s_buf_bytesize = opd_buf_size * kernel_pointer_size;
321
sbuf = xmalloc(s_buf_bytesize);
323
opd_reread_module_info();
325
for (i = 0; i < OPD_MAX_STATS; i++)
334
/* must be /after/ perfmon_init() at least */
335
if (atexit(clean_exit)) {
337
perror("oprofiled: couldn't set exit cleanup: ");
341
/* trigger kernel module setup before returning control to opcontrol */
343
gettimeofday(&tv, NULL);
345
start_time = tv.tv_sec;
346
sprintf(start_time_str, "%llu", start_time);
351
static void opd_26_start(void)
353
/* simple sleep-then-process loop */
354
opd_do_read(sbuf, s_buf_bytesize);
358
static void opd_26_exit(void)
361
printf("oprofiled stopped %s", op_get_time());
365
/* FIXME: free kernel images, sfiles etc. */
368
struct oprofiled_ops opd_26_ops = {
370
.start = opd_26_start,