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);
	}
}
Пример #3
0
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);
	}
}