opd_perfmon.c revision 5bbbe460405564a1aed8a67a13c43e9356ffc656
110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/**
210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @file opd_perfmon.c
310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * perfmonctl() handling
410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @remark Copyright 2003 OProfile authors
610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @remark Read the file COPYING
710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @author John Levon
910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project */
1010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
1110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#ifdef __ia64__
1210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
1310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/* need this for sched_setaffinity() in <sched.h> */
1410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define _GNU_SOURCE
1510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
1610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "oprofiled.h"
1710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "opd_perfmon.h"
1810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "opd_events.h"
1910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
2010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "op_cpu_type.h"
2110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "op_libiberty.h"
2210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "op_hw_config.h"
2310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
2410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <sys/syscall.h>
2510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <sys/wait.h>
2610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <unistd.h>
2710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <limits.h>
2810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <signal.h>
2910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <stdio.h>
3010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <stdlib.h>
3110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <string.h>
3210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <errno.h>
335bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng#include <sys/types.h>
345bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng#include <sys/stat.h>
3510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#ifdef HAVE_SCHED_SETAFFINITY
3610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <sched.h>
3710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#endif
3810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
3910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectextern op_cpu cpu_type;
4010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
4110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#ifndef HAVE_SCHED_SETAFFINITY
4210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
4310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/* many glibc's are not yet up to date */
4410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#ifndef __NR_sched_setaffinity
4510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define __NR_sched_setaffinity 1231
4610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#endif
4710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
4810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/* Copied from glibc's <sched.h> and <bits/sched.h> and munged */
4910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define CPU_SETSIZE	1024
5010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define __NCPUBITS	(8 * sizeof (unsigned long))
5110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projecttypedef struct
5210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
5310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	unsigned long __bits[CPU_SETSIZE / __NCPUBITS];
5410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project} cpu_set_t;
5510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
5610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define CPU_SET(cpu, cpusetp) \
5710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	((cpusetp)->__bits[(cpu)/__NCPUBITS] |= (1UL << ((cpu) % __NCPUBITS)))
5810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define CPU_ZERO(cpusetp) \
5910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	memset((cpusetp), 0, sizeof(cpu_set_t))
6010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
6110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic int
6210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectsched_setaffinity(pid_t pid, size_t len, cpu_set_t const * cpusetp)
6310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
6410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return syscall(__NR_sched_setaffinity, pid, len, cpusetp);
6510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
6610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#endif
6710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
6810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
6910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#ifndef HAVE_PERFMONCTL
7010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#ifndef __NR_perfmonctl
7110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define __NR_perfmonctl 1175
7210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#endif
7310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
7410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic int perfmonctl(int fd, int cmd, void * arg, int narg)
7510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
7610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return syscall(__NR_perfmonctl, fd, cmd, arg, narg);
7710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
7810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#endif
7910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
8010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
8110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic unsigned char uuid[16] = {
8210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	0x77, 0x7a, 0x6e, 0x61, 0x20, 0x65, 0x73, 0x69,
8310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	0x74, 0x6e, 0x72, 0x20, 0x61, 0x65, 0x0a, 0x6c
8410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project};
8510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
8610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
8710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic size_t nr_cpus;
8810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
8910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstruct child {
9010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	pid_t pid;
9110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	int up_pipe[2];
9210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	int ctx_fd;
9310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	sig_atomic_t sigusr1;
9410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	sig_atomic_t sigusr2;
9510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	sig_atomic_t sigterm;
9610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project};
9710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
9810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic struct child * children;
9910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
10010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void perfmon_start_child(int ctx_fd)
10110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
10210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (perfmonctl(ctx_fd, PFM_START, 0, 0) == -1) {
10310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		exit(EXIT_FAILURE);
10410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
10510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
10610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
10710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
10810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void perfmon_stop_child(int ctx_fd)
10910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
11010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (perfmonctl(ctx_fd, PFM_STOP, 0, 0) == -1) {
11110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		exit(EXIT_FAILURE);
11210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
11310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
11410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
11510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
11610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void child_sigusr1(int val __attribute__((unused)))
11710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
11810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size_t i;
11910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
12010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (i = 0; i < nr_cpus; ++i) {
12110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (children[i].pid == getpid()) {
12210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			children[i].sigusr1 = 1;
12310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			return;
12410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
12510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
12610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
12710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
12810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
12910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void child_sigusr2(int val __attribute__((unused)))
13010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
13110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size_t i;
13210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
13310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (i = 0; i < nr_cpus; ++i) {
13410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (children[i].pid == getpid()) {
13510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			children[i].sigusr2 = 1;
13610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			return;
13710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
13810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
13910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
14010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
14110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
14210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void child_sigterm(int val __attribute__((unused)))
14310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
14410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	kill(getppid(), SIGTERM);
14510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
14610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
14710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
14810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void set_affinity(size_t cpu)
14910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
15010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	cpu_set_t set;
1515bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	int err;
15210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
15310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	CPU_ZERO(&set);
15410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	CPU_SET(cpu, &set);
15510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
1565bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	err = sched_setaffinity(getpid(), sizeof(set), &set);
15710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
15810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (err == -1) {
1595bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		perror("Failed to set affinity");
16010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		exit(EXIT_FAILURE);
16110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
16210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
16310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
16410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
16510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void setup_signals(void)
16610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
16710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	struct sigaction act;
16810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	sigset_t mask;
16910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
17010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	sigemptyset(&mask);
17110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	sigaddset(&mask, SIGUSR1);
17210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	sigaddset(&mask, SIGUSR2);
17310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	sigprocmask(SIG_BLOCK, &mask, NULL);
17410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
17510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	act.sa_handler = child_sigusr1;
17610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	act.sa_flags = 0;
17710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	sigemptyset(&act.sa_mask);
17810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
17910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (sigaction(SIGUSR1, &act, NULL)) {
1805bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		perror("oprofiled: install of SIGUSR1 handler failed");
18110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		exit(EXIT_FAILURE);
18210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
18310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
18410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	act.sa_handler = child_sigusr2;
18510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	act.sa_flags = 0;
18610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	sigemptyset(&act.sa_mask);
18710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
18810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (sigaction(SIGUSR2, &act, NULL)) {
1895bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		perror("oprofiled: install of SIGUSR2 handler failed");
19010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		exit(EXIT_FAILURE);
19110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
19210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
19310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	act.sa_handler = child_sigterm;
19410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	act.sa_flags = 0;
19510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	sigemptyset(&act.sa_mask);
19610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
19710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (sigaction(SIGTERM, &act, NULL)) {
1985bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		perror("oprofiled: install of SIGTERM handler failed");
19910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		exit(EXIT_FAILURE);
20010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
20110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
20210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
20310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
20410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/** create the per-cpu context */
20510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void create_context(struct child * self)
20610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
20710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	pfarg_context_t ctx;
20810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	int err;
20910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
21010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	memset(&ctx, 0, sizeof(pfarg_context_t));
21110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	memcpy(&ctx.ctx_smpl_buf_id, &uuid, 16);
21210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	ctx.ctx_flags = PFM_FL_SYSTEM_WIDE;
21310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
21410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	err = perfmonctl(0, PFM_CREATE_CONTEXT, &ctx, 1);
21510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (err == -1) {
2165bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		perror("CREATE_CONTEXT failed");
21710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		exit(EXIT_FAILURE);
21810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
21910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
22010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	self->ctx_fd = ctx.ctx_fd;
22110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
22210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
22310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
22410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/** program the perfmon counters */
22510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void write_pmu(struct child * self)
22610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
22710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	pfarg_reg_t pc[OP_MAX_COUNTERS];
22810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	pfarg_reg_t pd[OP_MAX_COUNTERS];
22910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	int err;
23010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size_t i;
23110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
23210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	memset(pc, 0, sizeof(pc));
23310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	memset(pd, 0, sizeof(pd));
23410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
23510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define PMC_GEN_INTERRUPT (1UL << 5)
23610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define PMC_PRIV_MONITOR (1UL << 6)
23710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/* McKinley requires pmc4 to have bit 23 set (enable PMU).
23810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * It is supposedly ignored in other pmc registers.
23910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project */
24010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define PMC_MANDATORY (1UL << 23)
24110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define PMC_USER (1UL << 3)
24210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#define PMC_KERNEL (1UL << 0)
24310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (i = 0; i < op_nr_counters && opd_events[i].name; ++i) {
24410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		struct opd_event * event = &opd_events[i];
24510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		pc[i].reg_num = event->counter + 4;
24610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		pc[i].reg_value = PMC_GEN_INTERRUPT;
24710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		pc[i].reg_value |= PMC_PRIV_MONITOR;
24810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		pc[i].reg_value |= PMC_MANDATORY;
24910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		(event->user) ? (pc[i].reg_value |= PMC_USER)
25010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		              : (pc[i].reg_value &= ~PMC_USER);
25110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		(event->kernel) ? (pc[i].reg_value |= PMC_KERNEL)
25210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		                : (pc[i].reg_value &= ~PMC_KERNEL);
25310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		pc[i].reg_value &= ~(0xff << 8);
25410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		pc[i].reg_value |= ((event->value & 0xff) << 8);
25510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		pc[i].reg_value &= ~(0xf << 16);
25610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		pc[i].reg_value |= ((event->um & 0xf) << 16);
25710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		pc[i].reg_smpl_eventid = event->counter;
25810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
25910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
26010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (i = 0; i < op_nr_counters && opd_events[i].name; ++i) {
26110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		struct opd_event * event = &opd_events[i];
26210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		pd[i].reg_value = ~0UL - event->count + 1;
26310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		pd[i].reg_short_reset = ~0UL - event->count + 1;
26410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		pd[i].reg_num = event->counter + 4;
26510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
26610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
26710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	err = perfmonctl(self->ctx_fd, PFM_WRITE_PMCS, pc, i);
26810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (err == -1) {
2695bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		perror("Couldn't write PMCs");
27010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		exit(EXIT_FAILURE);
27110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
27210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
27310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	err = perfmonctl(self->ctx_fd, PFM_WRITE_PMDS, pd, i);
27410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (err == -1) {
2755bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		perror("Couldn't write PMDs");
27610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		exit(EXIT_FAILURE);
27710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
27810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
27910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
28010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
28110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void load_context(struct child * self)
28210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
28310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	pfarg_load_t load_args;
28410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	int err;
28510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
28610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	memset(&load_args, 0, sizeof(load_args));
28710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	load_args.load_pid = self->pid;
28810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
28910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	err = perfmonctl(self->ctx_fd, PFM_LOAD_CONTEXT, &load_args, 1);
29010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (err == -1) {
2915bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		perror("Couldn't load context");
29210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		exit(EXIT_FAILURE);
29310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
29410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
29510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
29610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
29710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void notify_parent(struct child * self, size_t cpu)
29810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
29910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (;;) {
30010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		ssize_t ret;
30110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		ret = write(self->up_pipe[1], &cpu, sizeof(size_t));
30210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (ret == sizeof(size_t))
30310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			break;
30410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (ret < 0 && errno != EINTR) {
3055bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng			perror("Failed to write child pipe:");
30610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			exit(EXIT_FAILURE);
30710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
30810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
30910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
31010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
3115bbbe460405564a1aed8a67a13c43e9356ffc656Ben Chengstatic struct child * inner_child;
3125bbbe460405564a1aed8a67a13c43e9356ffc656Ben Chengvoid close_pipe(void)
3135bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng{
3145bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	close(inner_child->up_pipe[1]);
3155bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng}
31610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
31710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void run_child(size_t cpu)
31810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
31910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	struct child * self = &children[cpu];
32010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
32110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	self->pid = getpid();
32210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	self->sigusr1 = 0;
32310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	self->sigusr2 = 0;
32410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	self->sigterm = 0;
32510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
3265bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	inner_child = self;
3275bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	if (atexit(close_pipe)){
3285bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		close_pipe();
3295bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		exit(EXIT_FAILURE);
3305bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	}
3315bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng
3325bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	umask(0);
3335bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	/* Change directory to allow directory to be removed */
3345bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	if (chdir("/") < 0) {
3355bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		perror("Unable to chdir to \"/\"");
3365bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		exit(EXIT_FAILURE);
3375bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	}
3385bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng
33910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	setup_signals();
34010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
34110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	set_affinity(cpu);
34210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
34310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	create_context(self);
34410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
34510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	write_pmu(self);
34610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
34710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	load_context(self);
34810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
34910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	notify_parent(self, cpu);
35010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
3515bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	/* Redirect standard files to /dev/null */
3525bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	freopen( "/dev/null", "r", stdin);
3535bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	freopen( "/dev/null", "w", stdout);
3545bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	freopen( "/dev/null", "w", stderr);
3555bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng
35610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (;;) {
35710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		sigset_t sigmask;
35810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		sigfillset(&sigmask);
35910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		sigdelset(&sigmask, SIGUSR1);
36010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		sigdelset(&sigmask, SIGUSR2);
36110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		sigdelset(&sigmask, SIGTERM);
36210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
36310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (self->sigusr1) {
36410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			perfmon_start_child(self->ctx_fd);
36510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			self->sigusr1 = 0;
36610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
36710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
36810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (self->sigusr2) {
36910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			perfmon_stop_child(self->ctx_fd);
37010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			self->sigusr2 = 0;
37110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
37210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
37310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		sigsuspend(&sigmask);
37410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
37510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
37610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
37710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
37810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void wait_for_child(struct child * child)
37910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
38010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size_t tmp;
38110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (;;) {
38210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		ssize_t ret;
38310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		ret = read(child->up_pipe[0], &tmp, sizeof(size_t));
38410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (ret == sizeof(size_t))
38510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			break;
3865bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		if ((ret < 0 && errno != EINTR) || ret == 0 ) {
3875bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng			perror("Failed to read child pipe");
38810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			exit(EXIT_FAILURE);
38910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
39010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
39110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	printf("Perfmon child up on CPU%d\n", (int)tmp);
39210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	fflush(stdout);
39310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
39410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	close(child->up_pipe[0]);
39510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
39610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
39710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic struct child* xen_ctx;
39810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
39910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectvoid perfmon_init(void)
40010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
40110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size_t i;
40210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	long nr;
40310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
40410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (cpu_type == CPU_TIMER_INT)
40510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return;
40610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
40710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!no_xen) {
40810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		xen_ctx = xmalloc(sizeof(struct child));
40910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		xen_ctx->pid = getpid();
41010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		xen_ctx->up_pipe[0] = -1;
41110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		xen_ctx->up_pipe[1] = -1;
41210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		xen_ctx->sigusr1 = 0;
41310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		xen_ctx->sigusr2 = 0;
41410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		xen_ctx->sigterm = 0;
41510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
41610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		create_context(xen_ctx);
41710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
41810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		write_pmu(xen_ctx);
41910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
42010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		load_context(xen_ctx);
42110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return;
42210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
42310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
42410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
42510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	nr = sysconf(_SC_NPROCESSORS_ONLN);
42610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (nr == -1) {
42710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		fprintf(stderr, "Couldn't determine number of CPUs.\n");
42810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		exit(EXIT_FAILURE);
42910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
43010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
43110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	nr_cpus = nr;
43210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
43310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	children = xmalloc(sizeof(struct child) * nr_cpus);
4345bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	bzero(children, sizeof(struct child) * nr_cpus);
43510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
43610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (i = 0; i < nr_cpus; ++i) {
43710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		int ret;
43810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
43910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (pipe(children[i].up_pipe)) {
4405bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng			perror("Couldn't create child pipe");
44110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			exit(EXIT_FAILURE);
44210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
44310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
44410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		ret = fork();
44510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (ret == -1) {
4465bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng			perror("Couldn't fork perfmon child");
44710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			exit(EXIT_FAILURE);
44810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		} else if (ret == 0) {
4495bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng			close(children[i].up_pipe[0]);
45010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			run_child(i);
45110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		} else {
45210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			children[i].pid = ret;
4535bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng			close(children[i].up_pipe[1]);
45410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			printf("Waiting on CPU%d\n", (int)i);
45510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			wait_for_child(&children[i]);
45610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
45710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
45810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
45910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
46010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
46110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectvoid perfmon_exit(void)
46210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
46310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size_t i;
46410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
46510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (cpu_type == CPU_TIMER_INT)
46610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return;
46710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
46810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!no_xen)
46910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return;
47010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
47110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (i = 0; i < nr_cpus; ++i) {
4725bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		if (children[i].pid) {
4735bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng			int c_pid = children[i].pid;
4745bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng			children[i].pid = 0;
4755bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng			if (kill(c_pid, SIGKILL)==0)
4765bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng				waitpid(c_pid, NULL, 0);
4775bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		}
47810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
47910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
48010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
48110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
48210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectvoid perfmon_start(void)
48310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
48410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size_t i;
48510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
48610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (cpu_type == CPU_TIMER_INT)
48710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return;
48810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
48910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!no_xen) {
49010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		perfmon_start_child(xen_ctx->ctx_fd);
49110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return;
49210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
49310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
4945bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	for (i = 0; i < nr_cpus; ++i) {
4955bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		if (kill(children[i].pid, SIGUSR1)) {
4965bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng			perror("Unable to start perfmon");
4975bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng			exit(EXIT_FAILURE);
4985bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		}
4995bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng	}
50010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
50110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
50210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
50310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectvoid perfmon_stop(void)
50410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
50510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size_t i;
50610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
50710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (cpu_type == CPU_TIMER_INT)
50810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return;
50910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
51010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!no_xen) {
51110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		perfmon_stop_child(xen_ctx->ctx_fd);
51210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return;
51310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
51410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
51510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (i = 0; i < nr_cpus; ++i)
5165bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		if (kill(children[i].pid, SIGUSR2)) {
5175bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng			perror("Unable to stop perfmon");
5185bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng			exit(EXIT_FAILURE);
5195bbbe460405564a1aed8a67a13c43e9356ffc656Ben Cheng		}
52010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
52110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
52210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#endif /* __ia64__ */
523