Port work-in-progress oprofile with Cortex-A9 support.
Change-Id: I26ecf3697c651dae31050081d6918ee5fc87915d
diff --git a/daemon/opd_perfmon.c b/daemon/opd_perfmon.c
index a1b158a..97f307c 100644
--- a/daemon/opd_perfmon.c
+++ b/daemon/opd_perfmon.c
@@ -30,6 +30,8 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#ifdef HAVE_SCHED_SETAFFINITY
#include <sched.h>
#endif
@@ -98,7 +100,6 @@
static void perfmon_start_child(int ctx_fd)
{
if (perfmonctl(ctx_fd, PFM_START, 0, 0) == -1) {
- perror("Couldn't start perfmon: ");
exit(EXIT_FAILURE);
}
}
@@ -107,7 +108,6 @@
static void perfmon_stop_child(int ctx_fd)
{
if (perfmonctl(ctx_fd, PFM_STOP, 0, 0) == -1) {
- perror("Couldn't stop perfmon: ");
exit(EXIT_FAILURE);
}
}
@@ -141,7 +141,6 @@
static void child_sigterm(int val __attribute__((unused)))
{
- printf("Child received SIGTERM, killing parent.\n");
kill(getppid(), SIGTERM);
}
@@ -149,15 +148,15 @@
static void set_affinity(size_t cpu)
{
cpu_set_t set;
+ int err;
CPU_ZERO(&set);
CPU_SET(cpu, &set);
- int err = sched_setaffinity(getpid(), sizeof(set), &set);
+ err = sched_setaffinity(getpid(), sizeof(set), &set);
if (err == -1) {
- fprintf(stderr, "Failed to set affinity: %s\n",
- strerror(errno));
+ perror("Failed to set affinity");
exit(EXIT_FAILURE);
}
}
@@ -178,7 +177,7 @@
sigemptyset(&act.sa_mask);
if (sigaction(SIGUSR1, &act, NULL)) {
- perror("oprofiled: install of SIGUSR1 handler failed: ");
+ perror("oprofiled: install of SIGUSR1 handler failed");
exit(EXIT_FAILURE);
}
@@ -187,7 +186,7 @@
sigemptyset(&act.sa_mask);
if (sigaction(SIGUSR2, &act, NULL)) {
- perror("oprofiled: install of SIGUSR2 handler failed: ");
+ perror("oprofiled: install of SIGUSR2 handler failed");
exit(EXIT_FAILURE);
}
@@ -196,7 +195,7 @@
sigemptyset(&act.sa_mask);
if (sigaction(SIGTERM, &act, NULL)) {
- perror("oprofiled: install of SIGTERM handler failed: ");
+ perror("oprofiled: install of SIGTERM handler failed");
exit(EXIT_FAILURE);
}
}
@@ -214,8 +213,7 @@
err = perfmonctl(0, PFM_CREATE_CONTEXT, &ctx, 1);
if (err == -1) {
- fprintf(stderr, "CREATE_CONTEXT failed: %s\n",
- strerror(errno));
+ perror("CREATE_CONTEXT failed");
exit(EXIT_FAILURE);
}
@@ -268,13 +266,13 @@
err = perfmonctl(self->ctx_fd, PFM_WRITE_PMCS, pc, i);
if (err == -1) {
- perror("Couldn't write PMCs: ");
+ perror("Couldn't write PMCs");
exit(EXIT_FAILURE);
}
err = perfmonctl(self->ctx_fd, PFM_WRITE_PMDS, pd, i);
if (err == -1) {
- perror("Couldn't write PMDs: ");
+ perror("Couldn't write PMDs");
exit(EXIT_FAILURE);
}
}
@@ -290,7 +288,7 @@
err = perfmonctl(self->ctx_fd, PFM_LOAD_CONTEXT, &load_args, 1);
if (err == -1) {
- perror("Couldn't load context: ");
+ perror("Couldn't load context");
exit(EXIT_FAILURE);
}
}
@@ -304,13 +302,17 @@
if (ret == sizeof(size_t))
break;
if (ret < 0 && errno != EINTR) {
- fprintf(stderr, "Failed to write child pipe with %s\n",
- strerror(errno));
+ perror("Failed to write child pipe:");
exit(EXIT_FAILURE);
}
}
}
+static struct child * inner_child;
+void close_pipe(void)
+{
+ close(inner_child->up_pipe[1]);
+}
static void run_child(size_t cpu)
{
@@ -321,6 +323,19 @@
self->sigusr2 = 0;
self->sigterm = 0;
+ inner_child = self;
+ if (atexit(close_pipe)){
+ close_pipe();
+ exit(EXIT_FAILURE);
+ }
+
+ umask(0);
+ /* Change directory to allow directory to be removed */
+ if (chdir("/") < 0) {
+ perror("Unable to chdir to \"/\"");
+ exit(EXIT_FAILURE);
+ }
+
setup_signals();
set_affinity(cpu);
@@ -333,6 +348,11 @@
notify_parent(self, cpu);
+ /* Redirect standard files to /dev/null */
+ freopen( "/dev/null", "r", stdin);
+ freopen( "/dev/null", "w", stdout);
+ freopen( "/dev/null", "w", stderr);
+
for (;;) {
sigset_t sigmask;
sigfillset(&sigmask);
@@ -341,15 +361,11 @@
sigdelset(&sigmask, SIGTERM);
if (self->sigusr1) {
- printf("PFM_START on CPU%d\n", (int)cpu);
- fflush(stdout);
perfmon_start_child(self->ctx_fd);
self->sigusr1 = 0;
}
if (self->sigusr2) {
- printf("PFM_STOP on CPU%d\n", (int)cpu);
- fflush(stdout);
perfmon_stop_child(self->ctx_fd);
self->sigusr2 = 0;
}
@@ -367,9 +383,8 @@
ret = read(child->up_pipe[0], &tmp, sizeof(size_t));
if (ret == sizeof(size_t))
break;
- if (ret < 0 && errno != EINTR) {
- fprintf(stderr, "Failed to read child pipe with %s\n",
- strerror(errno));
+ if ((ret < 0 && errno != EINTR) || ret == 0 ) {
+ perror("Failed to read child pipe");
exit(EXIT_FAILURE);
}
}
@@ -377,7 +392,6 @@
fflush(stdout);
close(child->up_pipe[0]);
- close(child->up_pipe[1]);
}
static struct child* xen_ctx;
@@ -417,25 +431,26 @@
nr_cpus = nr;
children = xmalloc(sizeof(struct child) * nr_cpus);
+ bzero(children, sizeof(struct child) * nr_cpus);
for (i = 0; i < nr_cpus; ++i) {
int ret;
if (pipe(children[i].up_pipe)) {
- perror("Couldn't create child pipe.\n");
+ perror("Couldn't create child pipe");
exit(EXIT_FAILURE);
}
ret = fork();
if (ret == -1) {
- fprintf(stderr, "Couldn't fork perfmon child.\n");
+ perror("Couldn't fork perfmon child");
exit(EXIT_FAILURE);
} else if (ret == 0) {
- printf("Running perfmon child on CPU%d.\n", (int)i);
- fflush(stdout);
+ close(children[i].up_pipe[0]);
run_child(i);
} else {
children[i].pid = ret;
+ close(children[i].up_pipe[1]);
printf("Waiting on CPU%d\n", (int)i);
wait_for_child(&children[i]);
}
@@ -454,8 +469,12 @@
return;
for (i = 0; i < nr_cpus; ++i) {
- kill(children[i].pid, SIGKILL);
- waitpid(children[i].pid, NULL, 0);
+ if (children[i].pid) {
+ int c_pid = children[i].pid;
+ children[i].pid = 0;
+ if (kill(c_pid, SIGKILL)==0)
+ waitpid(c_pid, NULL, 0);
+ }
}
}
@@ -472,8 +491,12 @@
return;
}
- for (i = 0; i < nr_cpus; ++i)
- kill(children[i].pid, SIGUSR1);
+ for (i = 0; i < nr_cpus; ++i) {
+ if (kill(children[i].pid, SIGUSR1)) {
+ perror("Unable to start perfmon");
+ exit(EXIT_FAILURE);
+ }
+ }
}
@@ -490,7 +513,10 @@
}
for (i = 0; i < nr_cpus; ++i)
- kill(children[i].pid, SIGUSR2);
+ if (kill(children[i].pid, SIGUSR2)) {
+ perror("Unable to stop perfmon");
+ exit(EXIT_FAILURE);
+ }
}
#endif /* __ia64__ */