void perfmon_init(void) { size_t i; long nr; if (cpu_type == CPU_TIMER_INT) return; if (!no_xen) { xen_ctx = xmalloc(sizeof(struct child)); xen_ctx->pid = getpid(); xen_ctx->up_pipe[0] = -1; xen_ctx->up_pipe[1] = -1; xen_ctx->sigusr1 = 0; xen_ctx->sigusr2 = 0; xen_ctx->sigterm = 0; create_context(xen_ctx); write_pmu(xen_ctx); load_context(xen_ctx); return; } nr = sysconf(_SC_NPROCESSORS_ONLN); if (nr == -1) { fprintf(stderr, "Couldn't determine number of CPUs.\n"); exit(EXIT_FAILURE); } 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"); exit(EXIT_FAILURE); } ret = fork(); if (ret == -1) { perror("Couldn't fork perfmon child"); exit(EXIT_FAILURE); } else if (ret == 0) { 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]); } } }
static void run_child(size_t cpu) { struct child * self = &children[cpu]; self->pid = getpid(); self->sigusr1 = 0; 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); create_context(self); write_pmu(self); load_context(self); 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); sigdelset(&sigmask, SIGUSR1); sigdelset(&sigmask, SIGUSR2); sigdelset(&sigmask, SIGTERM); if (self->sigusr1) { perfmon_start_child(self->ctx_fd); self->sigusr1 = 0; } if (self->sigusr2) { perfmon_stop_child(self->ctx_fd); self->sigusr2 = 0; } sigsuspend(&sigmask); } }
static void run_child(size_t cpu) { struct child * self = &children[cpu]; self->pid = getpid(); self->sigusr1 = 0; self->sigusr2 = 0; self->sigterm = 0; setup_signals(); set_affinity(cpu); create_context(self); write_pmu(self); load_context(self); notify_parent(self, cpu); for (;;) { sigset_t sigmask; sigfillset(&sigmask); sigdelset(&sigmask, SIGUSR1); sigdelset(&sigmask, SIGUSR2); 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; } sigsuspend(&sigmask); } }