blob: c0b29c746e705a60ab241ed85b53b46cfb8a3b85 [file] [log] [blame]
/*
* opcontrol/opcontrol.cpp
*/
#include "op_config.h"
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <dirent.h>
#include <sys/stat.h>
static int usage(const char* name);
static int echo(const char* str, const char* file);
static int read_num(const char* file);
static int start_profiler(int argc, char const * argv[]);
static int stop_profiler();
static int reset_profiler();
static int status_profiler();
int main(int argc, char const * argv[])
{
if (argc < 2)
return usage(argv[0]);
const char* tool = argv[1];
int ret = 0;
if (!strcmp("start", tool)) ret = start_profiler(argc-2, argv+2);
else if (!strcmp("stop", tool)) ret = stop_profiler();
else if (!strcmp("reset", tool)) ret = reset_profiler();
else if (!strcmp("status", tool)) ret = status_profiler();
return ret ? usage(argv[0]) : 0;
}
int usage(const char* name)
{
printf("usage: %s [start [-e event][-p type][-c depth][-i names]"
" | stop | reset | status]\n", name);
return 0;
}
int start_profiler(int argc, char const * argv[])
{
char const* backtrace_depth = "0";
if (argc&1)
return -1;
while (argc>0) {
if (!strcmp("-c", argv[0]))
backtrace_depth = argv[1];
else if (!strcmp("-p", argv[0]))
; // type
else if (!strcmp("-e", argv[0]))
; // event
else if (!strcmp("-i", argv[0]))
; // images
argc-=2;
argv+=2;
}
int err;
err = echo(backtrace_depth, OP_DRIVER_BASE"/backtrace_depth");
if (err) {
printf("couldn't set backtrace depth. backtraces disabled.\n");
}
err = echo("1", OP_DRIVER_BASE"/enable");
if (err) {
printf("couldn't start profiling, is the oprofile driver installed?\n");
return -1;
}
// XXX: start daemon with all good options ...
mkdir(OP_BASE_DIR, 644);
return 0;
}
int stop_profiler()
{
int dump, stop;
dump = echo("1", OP_DRIVER_BASE"/dump");
// XXX: should wait for complete_dump
usleep(250000);
stop = echo("0", OP_DRIVER_BASE"/enable");
if (dump || stop) {
printf("couldn't stop profiling, is the oprofile driver installed?\n");
return -1;
}
int num = read_num(OP_DRIVER_BASE"/stats/cpu0/sample_received");
printf("profiler stopped with %u samples received\n", num);
return 0;
}
int rm_dir_content(const char* path)
{
DIR* d = opendir(path);
if (d) {
struct dirent* de;
while ((de = readdir(d))) {
if(de->d_name[0] == '.') continue;
struct stat s;
char* tmp = (char*)malloc(strlen(path)+strlen(de->d_name)+2);
if (tmp) {
sprintf(tmp, "%s/%s", path, de->d_name);
if (lstat(tmp, &s) == 0) {
int mode = s.st_mode & S_IFMT;
if (mode == S_IFDIR) {
rm_dir_content(tmp);
rmdir(tmp);
} else if (mode == S_IFLNK) {
} else if (mode == S_IFSOCK) {
} else if (mode == S_IFREG) {
unlink(tmp);
}
}
free(tmp);
}
}
closedir(d);
}
return 0;
}
int reset_profiler()
{
echo("1", OP_DRIVER_BASE"/dump");
usleep(250000);
// should erase all samples
rm_dir_content(OP_BASE_DIR);
return 0;
}
int status_profiler()
{
int num = read_num(OP_DRIVER_BASE"/enable");
if (num >= 0) {
printf("profiler %s\n", num ? "started" : "not started");
num = read_num(OP_DRIVER_BASE"/stats/cpu0/sample_received");
printf(" %9u samples received\n", num);
num = read_num(OP_DRIVER_BASE"/stats/cpu0/backtrace_aborted");
printf(" %9u backtrace aborted\n", num);
num = read_num(OP_DRIVER_BASE"/stats/cpu0/sample_lost_overflow");
printf(" %9u samples lost overflow\n", num);
num = read_num(OP_DRIVER_BASE"/backtrace_depth");
printf(" %9u backtrace_depth\n", num);
return 0;
}
printf("couldn't get profiling status, is the oprofile driver installed?\n");
return -1;
}
int echo(const char* str, const char* file)
{
int fd = open(file, O_WRONLY);
if (fd<0)
return fd;
write(fd, str, strlen(str));
close(fd);
return 0;
}
int read_num(const char* file)
{
char buffer[256];
int fd = open(file, O_RDONLY);
if (fd<0) return -1;
int rd = read(fd, buffer, sizeof(buffer)-1);
buffer[rd] = 0;
return atoi(buffer);
}