Example #1
0
int create_perf_stat_counter(int pid, int system_wide)
{
	struct perf_event_attr attr; //cache miss
	memcpy(&attr, attrs, sizeof(struct perf_event_attr));

	if (scale)
		attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
				    PERF_FORMAT_TOTAL_TIME_RUNNING;

	if (system_wide) {
		unsigned int cpu;

		for (cpu = 0; cpu < nr_cpus; cpu++) {
			fd[cpu] = sys_perf_event_open(&attr, -1, cpu, -1, 0);
		}

		return fd[cpu - 1];
	} else {
		attr.inherit	     = inherit;
		attr.disabled	     = 0;
		attr.enable_on_exec = 1;

		return sys_perf_event_open(&attr, pid, -1, -1, 0);
	}
}
Example #2
0
int main(int argc, char *argv[])
{
    (void) argc; (void) argv;

    perf_event_attr attr, attr2;

    // Execution sur un seul CPU
    pid_t tid = gettid();
    cpu_set_t  mask;
    CPU_ZERO(&mask);
    CPU_SET(0, &mask);
    qDebug() << sched_setaffinity(0, sizeof(mask), &mask);

    //(perf_hw_cache_id) | (perf_hw_cache_op_id << 8) |
    //(perf_hw_cache_op_result_id << 16)

    // premiere structure d'attributs
    memset(&attr, 0, sizeof(attr));
    attr.size = sizeof(attr);
    attr.type = PERF_TYPE_HW_CACHE;
    attr.config = (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16);
    attr.inherit = 1;
    attr.disabled = 0;

    // Deuxieme structure
    memset(&attr2, 0, sizeof(attr2));
    attr2.size = sizeof(attr2);
    attr2.type = PERF_TYPE_HW_CACHE;
    attr2.config = (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16);
    attr2.inherit = 1;
    attr2.disabled = 0;

    //pid == 0 and cpu == -1
    //This measures the calling process/thread on any CPU.
    int fdRef = sys_perf_event_open(&attr, tid, -1, -1, 0);
    int fdMiss = sys_perf_event_open(&attr2, tid, -1, -1, 0);
    //int fdMiss = sys_perf_event_open(&attr2, tid, -1, fdRef, 0);

    QMap<int, double> results;
    for (qint64 len = 1; len < (1 << 26); len *= 2) {
        double miss_rate = experiment(len, fdRef, fdMiss);
        results.insert(len * sizeof(int), miss_rate);
    }

    // report
    std::cout << "size,miss_rate" << std::endl;
    for (int size : results.keys()) {
        std::cout << size << "," << results[size] << std::endl;
    }

    close(fdRef);
    close(fdMiss);
    return 0;
}
Example #3
0
static int
open_counter(size_t nr_switches)
{
    struct perf_event_attr attr;
    int fd;
    struct f_owner_ex own;

    memset(&attr, 0, sizeof(attr));
    attr.size = sizeof(attr);
    attr.type = PERF_TYPE_SOFTWARE;
    attr.config = PERF_COUNT_SW_CONTEXT_SWITCHES;
    attr.disabled = 1;
    attr.sample_period = nr_switches;

    fd = sys_perf_event_open(&attr, 0/*self*/, -1/*any cpu*/, -1, 0);
    if (0 > fd)
        err(1, "perf_event_open(cs, period=%u)", nr_switches);

    if (fcntl(fd, F_SETFL, O_ASYNC))
        err(1, "fcntl(O_ASYNC)");

    own.type = F_OWNER_TID;
    own.pid = sys_gettid();
    if (fcntl(fd, F_SETOWN_EX, &own))
        err(1, "fcntl(SETOWN_EX)");

    if (fcntl(fd, F_SETSIG, SIGIO))
        err(1, "fcntl(SETSIG, SIGIO)");

    return fd;
}
Example #4
0
static int perf_event_open_gen(struct perf_event_attr *attr,
                               int group_fd)
{

    // Group leader: Request time values for reference (so we can
    // detect multiplexing). Also ask for the whole group to return
    // results at the same time.
#ifdef USE_PERF_FORMAT_GROUP
    if (group_fd == -1) {
#endif
        attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED
                          | PERF_FORMAT_TOTAL_TIME_RUNNING
#ifdef USE_PERF_FORMAT_GROUP
                          | PERF_FORMAT_GROUP
#endif
                          ;
#ifdef USE_PERF_FORMAT_GROUP
    }
#endif

    // Exclude kernel and hypervisor, start disabled
    attr->exclude_kernel = 1;
    attr->exclude_hv = 1;
    attr->disabled = 1;
#ifndef USE_PERF_FORMAT_GROUP
    attr->inherit = 1;
#endif

    // Create the performance counter
    return sys_perf_event_open(attr, 0, -1, group_fd, 0);
}
int perf_open(int inherit, counter_config config)
{
    perf_event_attr attr;
    memset(&attr,0,sizeof(attr));
    attr.size = sizeof(attr);
    attr.exclude_kernel = 1;
    attr.type = PERF_TYPE_HARDWARE;

    switch(config){
        case INST :
            attr.config = PERF_COUNT_HW_INSTRUCTIONS;
            break;
        case HW_CYCLES :
            attr.config = PERF_COUNT_HW_CPU_CYCLES;
            break;
        default :
            fprintf(stderr, "Invalid counter configuration.\n");
            exit(EXIT_FAILURE);
            break;
    }

    attr.inherit = inherit;
    attr.disabled = 0;
    return sys_perf_event_open(&attr, 0, -1, -1, 0);
}
Example #6
0
/*
 *  perf_open()
 *	open perf, get leader and perf fd's
 */
int perf_open(stress_perf_t *sp)
{
	size_t i;

	if (!sp)
		return -1;
	if (g_shared->perf.no_perf)
		return -1;

	(void)memset(sp, 0, sizeof(*sp));
	sp->perf_opened = 0;

	for (i = 0; i < STRESS_PERF_MAX; i++) {
		sp->perf_stat[i].fd = -1;
		sp->perf_stat[i].counter = 0;
	}

	for (i = 0; i < STRESS_PERF_MAX && perf_info[i].label; i++) {
		if (perf_info[i].config != UNRESOLVED) {
			struct perf_event_attr attr;

			(void)memset(&attr, 0, sizeof(attr));
			attr.type = perf_info[i].type;
			attr.config = perf_info[i].config;
			attr.disabled = 1;
			attr.inherit = 1;
			attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
					   PERF_FORMAT_TOTAL_TIME_RUNNING;
			attr.size = sizeof(attr);
			sp->perf_stat[i].fd =
				sys_perf_event_open(&attr, 0, -1, -1, 0);
			if (sp->perf_stat[i].fd > -1)
				sp->perf_opened++;
		}
	}
	if (!sp->perf_opened) {
		int ret;

		ret = shim_pthread_spin_lock(&g_shared->perf.lock);
		if (!ret) {
			pr_dbg("perf: spin lock on perf.lock failed: %d (%s)\n",
				ret, strerror(ret));
			return -1;
		}
		if (!g_shared->perf.no_perf) {
			pr_dbg("perf: perf_event_open failed, no "
				"perf events [%u]\n", getpid());
			g_shared->perf.no_perf = true;
		}
		ret = shim_pthread_spin_unlock(&g_shared->perf.lock);
		if (!ret) {
			pr_dbg("perf: spin unlock on perf.lock failed: %d (%s)\n",
				ret, strerror(ret));
			return -1;
		}
		return -1;
	}

	return 0;
}
Example #7
0
static int sampling_start(int *pmu_fd, int freq)
{
	int i;

	struct perf_event_attr pe_sample_attr = {
		.type = PERF_TYPE_SOFTWARE,
		.freq = 1,
		.sample_period = freq,
		.config = PERF_COUNT_SW_CPU_CLOCK,
		.inherit = 1,
	};

	for (i = 0; i < nr_cpus; i++) {
		pmu_fd[i] = sys_perf_event_open(&pe_sample_attr, -1 /* pid */, i,
					    -1 /* group_fd */, 0 /* flags */);
		if (pmu_fd[i] < 0) {
			fprintf(stderr, "ERROR: Initializing perf sampling\n");
			return 1;
		}
		assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_SET_BPF,
			     prog_fd[0]) == 0);
		assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0) == 0);
	}

	return 0;
}

static void sampling_end(int *pmu_fd)
{
	int i;

	for (i = 0; i < nr_cpus; i++)
		close(pmu_fd[i]);
}
Example #8
0
static int __event(bool is_x, void *addr, struct perf_event_attr *attr)
{
	int fd;

	memset(attr, 0, sizeof(struct perf_event_attr));
	attr->type = PERF_TYPE_BREAKPOINT;
	attr->size = sizeof(struct perf_event_attr);

	attr->config = 0;
	attr->bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W;
	attr->bp_addr = (unsigned long) addr;
	attr->bp_len = sizeof(long);

	attr->sample_period = 1;
	attr->sample_type = PERF_SAMPLE_IP;

	attr->exclude_kernel = 1;
	attr->exclude_hv = 1;

	fd = sys_perf_event_open(attr, -1, 0, -1,
				 perf_event_open_cloexec_flag());
	if (fd < 0) {
		pr_debug("failed opening event %llx\n", attr->config);
		return TEST_FAIL;
	}

	return fd;
}
Example #9
0
static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
			      struct thread_map *threads)
{
	int cpu, thread;

	if (evsel->fd == NULL &&
	    perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
		return -1;

	for (cpu = 0; cpu < cpus->nr; cpu++) {
		for (thread = 0; thread < threads->nr; thread++) {
			FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
								     threads->map[thread],
								     cpus->map[cpu], -1, 0);
			if (FD(evsel, cpu, thread) < 0)
				goto out_close;
		}
	}

	return 0;

out_close:
	do {
		while (--thread >= 0) {
			close(FD(evsel, cpu, thread));
			FD(evsel, cpu, thread) = -1;
		}
		thread = threads->nr;
	} while (--cpu >= 0);
	return -1;
}
Example #10
0
bool PerfGroup::prepareCPU(const int cpu) {
	logg->logMessage("%s(%s:%i): Onlining cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu);

	for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
		if (mKeys[i] < 0) {
			continue;
		}

		const int offset = i * gSessionData->mCores;
		if (mFds[cpu + offset] >= 0) {
			logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__);
			return false;
		}

		logg->logMessage("%s(%s:%i): perf_event_open cpu: %i type: %lli config: %lli sample: %lli sample_type: %lli", __FUNCTION__, __FILE__, __LINE__, cpu, (long long)mAttrs[i].type, (long long)mAttrs[i].config, (long long)mAttrs[i].sample_period, (long long)mAttrs[i].sample_type);
		mFds[cpu + offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, i == 0 ? -1 : mFds[cpu], i == 0 ? 0 : PERF_FLAG_FD_OUTPUT);
		if (mFds[cpu + offset] < 0) {
			logg->logMessage("%s(%s:%i): failed %s", __FUNCTION__, __FILE__, __LINE__, strerror(errno));
			continue;
		}

		if (!mPb->useFd(cpu, mFds[cpu + offset], mFds[cpu])) {
			logg->logMessage("%s(%s:%i): PerfBuffer::useFd failed", __FUNCTION__, __FILE__, __LINE__);
			return false;
		}
	}

	return true;
}
Example #11
0
bool
PerfMeasurement::canMeasureSomething()
{
    // Find out if the kernel implements the performance measurement
    // API.  If it doesn't, syscall(__NR_perf_event_open, ...) is
    // guaranteed to return -1 and set errno to ENOSYS.
    //
    // We set up input parameters that should provoke an EINVAL error
    // from a kernel that does implement perf_event_open, but we can't
    // be sure it will (newer kernels might add more event types), so
    // we have to take care to close any valid fd it might return.

    struct perf_event_attr attr;
    memset(&attr, 0, sizeof(attr));
    attr.size = sizeof(attr);
    attr.type = PERF_TYPE_MAX;

    int fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
    if (fd >= 0) {
        close(fd);
        return true;
    } else {
        return errno != ENOSYS;
    }
}
Example #12
0
static bool perfPoll(struct perf_event_attr *const pea) {
	int fd = sys_perf_event_open(pea, -1, 0, -1, 0);
	if (fd < 0) {
		return false;
	}
	close(fd);
	return true;
}
Example #13
0
int PerfGroup::prepareCPU(const int cpu, Monitor *const monitor) {
	logg.logMessage("Onlining cpu %i", cpu);

	for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
		if (mKeys[i] < 0) {
			continue;
		}

		if ((cpu != 0) && !(mFlags[i] & PERF_GROUP_PER_CPU)) {
			continue;
		}

		if ((mFlags[i] & PERF_GROUP_PER_CPU) && !(mFlags[i] & PERF_GROUP_ALL_CLUSTERS) && gSessionData.mSharedData->mClusters[gSessionData.mSharedData->mClusterIds[cpu]] != mClusters[i]) {
			continue;
		}

		const int offset = i * gSessionData.mCores + cpu;
		if (mFds[offset] >= 0) {
			logg.logMessage("cpu already online or not correctly cleaned up");
			return PG_FAILURE;
		}

		logg.logMessage("perf_event_open cpu: %i type: %i config: %lli sample: %lli sample_type: 0x%llx pinned: %lli mmap: %lli comm: %lli freq: %lli task: %lli sample_id_all: %lli", cpu, mAttrs[i].type, mAttrs[i].config, mAttrs[i].sample_period, mAttrs[i].sample_type, mAttrs[i].pinned, mAttrs[i].mmap, mAttrs[i].comm, mAttrs[i].freq, mAttrs[i].task, mAttrs[i].sample_id_all);
		mFds[offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, mAttrs[i].pinned ? -1 : mFds[mLeaders[getEffectiveType(mAttrs[i].type, mFlags[i])] * gSessionData.mCores + cpu], mAttrs[i].pinned ? 0 : PERF_FLAG_FD_OUTPUT);
		if (mFds[offset] < 0) {
			logg.logMessage("failed %s", strerror(errno));
			if (errno == ENODEV) {
				// The core is offline
				return PG_CPU_OFFLINE;
			}
			if (errno == ENOENT) {
				// This event doesn't apply to this CPU but should apply to a different one, ex bL
				continue;
			}
			logg.logMessage("perf_event_open failed");
			return PG_FAILURE;
		}

		if (!mPb->useFd(cpu, mFds[offset])) {
			logg.logMessage("PerfBuffer::useFd failed");
			return PG_FAILURE;
		}


		if (!monitor->add(mFds[offset])) {
			logg.logMessage("Monitor::add failed");
			return PG_FAILURE;
		}
	}

	return PG_SUCCESS;
}
Example #14
0
File: evsel.c Project: kprog/linux
static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
			      struct thread_map *threads, bool group,
			      struct xyarray *group_fds)
{
	int cpu, thread;
	unsigned long flags = 0;
	int pid = -1, err;

	if (evsel->fd == NULL &&
	    perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
		return -ENOMEM;

	if (evsel->cgrp) {
		flags = PERF_FLAG_PID_CGROUP;
		pid = evsel->cgrp->fd;
	}

	for (cpu = 0; cpu < cpus->nr; cpu++) {
		int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1;

		for (thread = 0; thread < threads->nr; thread++) {

			if (!evsel->cgrp)
				pid = threads->map[thread];

			FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
								     pid,
								     cpus->map[cpu],
								     group_fd, flags);
			if (FD(evsel, cpu, thread) < 0) {
				err = -errno;
				goto out_close;
			}

			if (group && group_fd == -1)
				group_fd = FD(evsel, cpu, thread);
		}
	}

	return 0;

out_close:
	do {
		while (--thread >= 0) {
			close(FD(evsel, cpu, thread));
			FD(evsel, cpu, thread) = -1;
		}
		thread = threads->nr;
	} while (--cpu >= 0);
	return err;
}
Example #15
0
static int perf_flag_probe(void)
{
	/* use 'safest' configuration as used in perf_evsel__fallback() */
	struct perf_event_attr attr = {
		.type = PERF_COUNT_SW_CPU_CLOCK,
		.config = PERF_COUNT_SW_CPU_CLOCK,
	};
	int fd;
	int err;

	/* check cloexec flag */
	fd = sys_perf_event_open(&attr, 0, -1, -1,
				 PERF_FLAG_FD_CLOEXEC);
	err = errno;

	if (fd >= 0) {
		close(fd);
		return 1;
	}

	WARN_ONCE(err != EINVAL,
		  "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
		  err, strerror(err));

	/* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
	fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
	err = errno;

	if (WARN_ONCE(fd < 0,
		      "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
		      err, strerror(err)))
		return -1;

	close(fd);

	return 0;
}
Example #16
0
static int sampling_do_open(PyObject *obj)
{
    int tid;
    int flags;
    PyPerfEvent *ev;
    struct f_owner_ex fown;
    struct perf_event_attr attr;

    if (!PyPerfEvent_CheckExact(obj))
        return -1;
    ev = (PyPerfEvent *)obj;
    tid = gettid();

    /* Open the perf event */
    attr = ev->attr;
    attr.disabled = 0; /* do not start the event yet */
    attr.watermark = 1;
    attr.wakeup_events = 1;
    ev->fd = sys_perf_event_open(&attr, tid, -1, -1, 0);
    if (ev->fd < 0) {
        ev->status = EVENT_STATUS_FAILED;
        return -1;
    }

    /* Configure fasync */
    fown.type = F_OWNER_TID;
    fown.pid = tid;
    if (fcntl(ev->fd, F_SETOWN_EX, &fown) < 0)
        goto fail;

    flags = fcntl(ev->fd, F_GETFL);
    if (fcntl(ev->fd, F_SETFL, flags | FASYNC | O_ASYNC) < 0)
        goto fail;

    ev->status = EVENT_STATUS_OPENED;
    xev = ev;
    __sync_synchronize();
    ioctl(xev->fd, PERF_EVENT_IOC_REFRESH, 1);
    ioctl(xev->fd, PERF_EVENT_IOC_ENABLE, 0);
    return 0;

fail:
    close(ev->fd);
    ev->fd = -1;
    ev->status = EVENT_STATUS_FAILED;
    PyErr_SetString(PyExc_RuntimeError, "fcntl() failed");
    return -1;
}
Example #17
0
static void test_perf_event_task(struct perf_event_attr *attr)
{
	int pmu_fd;

	/* open task bound event */
	pmu_fd = sys_perf_event_open(attr, 0, -1, -1, 0);
	if (pmu_fd < 0) {
		printf("sys_perf_event_open failed\n");
		return;
	}
	assert(ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd[0]) == 0);
	assert(ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0) == 0);
	system("dd if=/dev/zero of=/dev/null count=5000k");
	print_stacks();
	close(pmu_fd);
}
Example #18
0
static int self_open_counters(void)
{
	struct perf_event_attr attr;
	int fd;

	memset(&attr, 0, sizeof(attr));

	attr.type = PERF_TYPE_SOFTWARE;
	attr.config = PERF_COUNT_SW_TASK_CLOCK;

	fd = sys_perf_event_open(&attr, 0, -1, -1, 0);

	if (fd < 0)
		pr_err("Error: sys_perf_event_open() syscall returned "
		       "with %d (%s)\n", fd, strerror(errno));
	return fd;
}
static int create_perf_counter(struct perf_setup_s *p)
{
	struct cpu_map *cpus;
	int cpu;

	cpus = cpu_map__new(NULL);
	if (p == NULL)
		return PERF_PERIODIC_ERROR;
	for (cpu = 0; cpu < cpus->nr; cpu++) {
		if (((1 << cpu) & cpumask) == 0)
			continue;
		p->perf_fd[cpu] = sys_perf_event_open(p->attr, target_pid, cpu,
					-1, 0);
		if (p->perf_fd[cpu] < 0)
			return PERF_PERIODIC_ERROR;
	}
	return 0;
}
Example #20
0
static int self_open_counters(struct perf_sched *sched, unsigned long cur_task)
{
	struct perf_event_attr attr;
	char sbuf[STRERR_BUFSIZE], info[STRERR_BUFSIZE];
	int fd;
	struct rlimit limit;
	bool need_privilege = false;

	memset(&attr, 0, sizeof(attr));

	attr.type = PERF_TYPE_SOFTWARE;
	attr.config = PERF_COUNT_SW_TASK_CLOCK;

force_again:
	fd = sys_perf_event_open(&attr, 0, -1, -1,
				 perf_event_open_cloexec_flag());

	if (fd < 0) {
		if (errno == EMFILE) {
			if (sched->force) {
				BUG_ON(getrlimit(RLIMIT_NOFILE, &limit) == -1);
				limit.rlim_cur += sched->nr_tasks - cur_task;
				if (limit.rlim_cur > limit.rlim_max) {
					limit.rlim_max = limit.rlim_cur;
					need_privilege = true;
				}
				if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
					if (need_privilege && errno == EPERM)
						strcpy(info, "Need privilege\n");
				} else
					goto force_again;
			} else
				strcpy(info, "Have a try with -f option\n");
		}
		pr_err("Error: sys_perf_event_open() syscall returned "
		       "with %d (%s)\n%s", fd,
		       strerror_r(errno, sbuf, sizeof(sbuf)), info);
		exit(EXIT_FAILURE);
	}
	return fd;
}
Example #21
0
static void test_perf_event_all_cpu(struct perf_event_attr *attr)
{
	int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
	int *pmu_fd = malloc(nr_cpus * sizeof(int));
	int i;

	/* open perf_event on all cpus */
	for (i = 0; i < nr_cpus; i++) {
		pmu_fd[i] = sys_perf_event_open(attr, -1, i, -1, 0);
		if (pmu_fd[i] < 0) {
			printf("sys_perf_event_open failed\n");
			goto all_cpu_err;
		}
		assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_SET_BPF, prog_fd[0]) == 0);
		assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0) == 0);
	}
	system("dd if=/dev/zero of=/dev/null count=5000k");
	print_stacks();
all_cpu_err:
	for (i--; i >= 0; i--)
		close(pmu_fd[i]);
	free(pmu_fd);
}
Example #22
0
static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
{
	bool is_socket = strncmp(event, "socket", 6) == 0;
	bool is_kprobe = strncmp(event, "kprobe/", 7) == 0;
	bool is_kretprobe = strncmp(event, "kretprobe/", 10) == 0;
	bool is_tracepoint = strncmp(event, "tracepoint/", 11) == 0;
	bool is_xdp = strncmp(event, "xdp", 3) == 0;
	bool is_perf_event = strncmp(event, "perf_event", 10) == 0;
	bool is_cgroup_skb = strncmp(event, "cgroup/skb", 10) == 0;
	bool is_cgroup_sk = strncmp(event, "cgroup/sock", 11) == 0;
	size_t insns_cnt = size / sizeof(struct bpf_insn);
	enum bpf_prog_type prog_type;
	char buf[256];
	int fd, efd, err, id;
	struct perf_event_attr attr = {};

	attr.type = PERF_TYPE_TRACEPOINT;
	attr.sample_type = PERF_SAMPLE_RAW;
	attr.sample_period = 1;
	attr.wakeup_events = 1;

	if (is_socket) {
		prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
	} else if (is_kprobe || is_kretprobe) {
		prog_type = BPF_PROG_TYPE_KPROBE;
	} else if (is_tracepoint) {
		prog_type = BPF_PROG_TYPE_TRACEPOINT;
	} else if (is_xdp) {
		prog_type = BPF_PROG_TYPE_XDP;
	} else if (is_perf_event) {
		prog_type = BPF_PROG_TYPE_PERF_EVENT;
	} else if (is_cgroup_skb) {
		prog_type = BPF_PROG_TYPE_CGROUP_SKB;
	} else if (is_cgroup_sk) {
		prog_type = BPF_PROG_TYPE_CGROUP_SOCK;
	} else {
		printf("Unknown event '%s'\n", event);
		return -1;
	}

	fd = bpf_load_program(prog_type, prog, insns_cnt, license, kern_version,
			      bpf_log_buf, BPF_LOG_BUF_SIZE);
	if (fd < 0) {
		printf("bpf_load_program() err=%d\n%s", errno, bpf_log_buf);
		return -1;
	}

	prog_fd[prog_cnt++] = fd;

	if (is_xdp || is_perf_event || is_cgroup_skb || is_cgroup_sk)
		return 0;

	if (is_socket) {
		event += 6;
		if (*event != '/')
			return 0;
		event++;
		if (!isdigit(*event)) {
			printf("invalid prog number\n");
			return -1;
		}
		return populate_prog_array(event, fd);
	}

	if (is_kprobe || is_kretprobe) {
		if (is_kprobe)
			event += 7;
		else
			event += 10;

		if (*event == 0) {
			printf("event name cannot be empty\n");
			return -1;
		}

		if (isdigit(*event))
			return populate_prog_array(event, fd);

		snprintf(buf, sizeof(buf),
			 "echo '%c:%s %s' >> /sys/kernel/debug/tracing/kprobe_events",
			 is_kprobe ? 'p' : 'r', event, event);
		err = system(buf);
		if (err < 0) {
			printf("failed to create kprobe '%s' error '%s'\n",
			       event, strerror(errno));
			return -1;
		}

		strcpy(buf, DEBUGFS);
		strcat(buf, "events/kprobes/");
		strcat(buf, event);
		strcat(buf, "/id");
	} else if (is_tracepoint) {
		event += 11;

		if (*event == 0) {
			printf("event name cannot be empty\n");
			return -1;
		}
		strcpy(buf, DEBUGFS);
		strcat(buf, "events/");
		strcat(buf, event);
		strcat(buf, "/id");
	}

	efd = open(buf, O_RDONLY, 0);
	if (efd < 0) {
		printf("failed to open event %s\n", event);
		return -1;
	}

	err = read(efd, buf, sizeof(buf));
	if (err < 0 || err >= sizeof(buf)) {
		printf("read from '%s' failed '%s'\n", event, strerror(errno));
		return -1;
	}

	close(efd);

	buf[err] = 0;
	id = atoi(buf);
	attr.config = id;

	efd = sys_perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0);
	if (efd < 0) {
		printf("event %d fd %d err %s\n", id, efd, strerror(errno));
		return -1;
	}
	event_fd[prog_cnt - 1] = efd;
	ioctl(efd, PERF_EVENT_IOC_ENABLE, 0);
	ioctl(efd, PERF_EVENT_IOC_SET_BPF, fd);

	return 0;
}
Example #23
0
static int perf_flag_probe(void)
{
	/* use 'safest' configuration as used in perf_evsel__fallback() */
	struct perf_event_attr attr = {
		.type = PERF_TYPE_SOFTWARE,
		.config = PERF_COUNT_SW_CPU_CLOCK,
		.exclude_kernel = 1,
	};
	int fd;
	int err;
	int cpu;
	pid_t pid = -1;
	char sbuf[STRERR_BUFSIZE];

	cpu = sched_getcpu();
	if (cpu < 0)
		cpu = 0;

	/*
	 * Using -1 for the pid is a workaround to avoid gratuitous jump label
	 * changes.
	 */
	while (1) {
		/* check cloexec flag */
		fd = sys_perf_event_open(&attr, pid, cpu, -1,
					 PERF_FLAG_FD_CLOEXEC);
		if (fd < 0 && pid == -1 && errno == EACCES) {
			pid = 0;
			continue;
		}
		break;
	}
	err = errno;

	if (fd >= 0) {
		close(fd);
		return 1;
	}

	WARN_ONCE(err != EINVAL && err != EBUSY,
		  "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
		  err, strerror_r(err, sbuf, sizeof(sbuf)));

	/* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
	while (1) {
		fd = sys_perf_event_open(&attr, pid, cpu, -1, 0);
		if (fd < 0 && pid == -1 && errno == EACCES) {
			pid = 0;
			continue;
		}
		break;
	}
	err = errno;

	if (fd >= 0)
		close(fd);

	if (WARN_ONCE(fd < 0 && err != EBUSY,
		      "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
		      err, strerror_r(err, sbuf, sizeof(sbuf))))
		return -1;

	return 0;
}

unsigned long perf_event_open_cloexec_flag(void)
{
	static bool probed;

	if (!probed) {
		if (perf_flag_probe() <= 0)
			flag = 0;
		probed = true;
	}

	return flag;
}
Example #24
0
static void create_perf_event(void)
{
	struct perf_event_attr attr;
	int ret;

	struct {
		__u64 count;
		__u64 time_enabled;
		__u64 time_running;
		__u64 id;
	} read_data;

	memset(&attr, 0, sizeof(attr));

	attr.read_format	= PERF_FORMAT_TOTAL_TIME_ENABLED |
				  PERF_FORMAT_TOTAL_TIME_RUNNING |
				  PERF_FORMAT_ID;

	attr.sample_freq 	= 0;
	attr.sample_period	= 1;
	attr.sample_type	|= PERF_SAMPLE_RAW;

	attr.mmap		= 1;
	attr.comm		= 1;
	attr.inherit		= 0;
	attr.disabled		= 1;

	attr.type		= PERF_TYPE_TRACEPOINT;
	attr.config		= get_trace_type();

	if (attr.config <= 0)
		return;

	perf_fd = sys_perf_event_open(&attr, -1, 0, -1, 0);

	if (perf_fd < 0) {
		fprintf(stderr, "Perf syscall failed: %i / %i (%s)\n", perf_fd, errno, strerror(errno));
		return;
	}
	if (read(perf_fd, &read_data, sizeof(read_data)) == -1) {
		perror("Unable to read perf file descriptor\n");
		exit(-1);
	}

	fcntl(perf_fd, F_SETFL, O_NONBLOCK);

	perf_mmap = mmap(NULL, (128+1)*getpagesize(),
				PROT_READ | PROT_WRITE, MAP_SHARED, perf_fd, 0);
	if (perf_mmap == MAP_FAILED) {
		fprintf(stderr, "failed to mmap with %d (%s)\n", errno, strerror(errno));
		return;
	}

	ret = ioctl(perf_fd, PERF_EVENT_IOC_ENABLE);

	if (ret < 0)
		fprintf(stderr, "failed to enable perf \n");

	pc = perf_mmap;
	data_mmap = perf_mmap + getpagesize();


}
Example #25
0
HRESULT CaPerfEvent::startEvent(bool enable)
{
    PerfPmuTarget& pmuTgt = m_profConfig->getPMUTarget();
    const CAThreadVec& threadVec = m_profConfig->getThreadVec();

    size_t nbr = m_nbrfds;

    OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_DEBUG, L"nbr(%d) in startEvent", nbr);

    pid_t pid = -1;
    int group_fd = -1;
    int ret;
    int cpu;
    int fd;

    // Set perf_event_attr::disabled field
    m_attr.disabled = ~enable;

    if (pmuTgt.isSWP())
    {
        for (size_t i = 0; i < nbr; i++)
        {
            cpu = pmuTgt.m_pCpus[i];

            fd = sys_perf_event_open(&m_attr, pid, cpu, group_fd, 0);
            int err = errno;

            if (fd < 0)
            {
                OS_OUTPUT_DEBUG_LOG(L"sys_perf_event_open failed..", OS_DEBUG_LOG_ERROR);

                if ((EACCES == err) || (EPERM == err))
                {
                    OS_OUTPUT_DEBUG_LOG(L"sys_perf_event_open failed due to Access Permissions...", OS_DEBUG_LOG_EXTENSIVE);
                    return E_ACCESSDENIED;
                }
                else if (ENODEV == err)
                {
                    // invalid cpu list
                    OS_OUTPUT_DEBUG_LOG(L"sys_perf_event_open failed - ENODEV...", OS_DEBUG_LOG_EXTENSIVE);
                    return E_INVALIDARG;
                }
                else if (ENOENT == err)
                {
                    // invalid cpu list
                    OS_OUTPUT_DEBUG_LOG(L"sys_perf_event_open failed - ENOENT...", OS_DEBUG_LOG_EXTENSIVE);
                    return E_INVALIDARG;
                }
                else if (EINVAL == err)
                {
                    // invalid cpu list
                    OS_OUTPUT_DEBUG_LOG(L"sys_perf_event_open failed - EINVAL...", OS_DEBUG_LOG_EXTENSIVE);
                    return E_INVALIDARG;
                }
                else
                {
                    OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_EXTENSIVE, L"sys_perf_event_open failed - errno(%d)", err);
                    return E_FAIL;
                }
            }
            else
            {
                OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_EXTENSIVE, L"for cpu(%d) fd(%d)", cpu, fd);
            }

            m_pCountData[i].m_fd = fd;

            // If the event is sampling event, get the sample-id
            // We set the attr::read_format to PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_TOTAL_TIME_RUNNING
            // | PERF_FORMAT_ID;
            // for this the format of the data returned by read() on the fd is:
            //      struct read_format {
            //         u64      value;
            //         u64      time_enabled;
            //         u64      time_running;
            //         u64      id;
            //      }
            //
            if (m_samplingEvent)
            {
                ret = readn(fd, m_pCountData[i].m_values, (PERF_MAX_NBR_VALUES * sizeof(uint64_t)));

                // on error, return
                if (-1 == ret)
                {
                    OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_ERROR, L"error in reading samplie-id for event(%d, %lx), fd(%d) errno(%d)\n",
                                               m_attr.type, m_attr.config, fd, errno);
                    return E_FAIL;
                }

                m_pCountData[i].m_sampleId =  m_pCountData[i].m_values[3];

                // Now push this into m_eventDataList
                // TODO: Eventually we will discard pCountData stuff
                OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_EXTENSIVE, L"push elemnt in m_eventDataList i(%d)\n", i);
                m_eventDataList.push_back(m_pCountData[i]);
            }
        }
    }
    else
    {
        OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_DEBUG, L"nbrPids(%d) nbrThreads(%d).\n", pmuTgt.m_nbrPids, threadVec.size());

        int cnt = 0;

        for (size_t i = 0; i < pmuTgt.m_nbrCpus; i++)
        {
            cpu = pmuTgt.m_pCpus[i];

            for (size_t j = 0; j < threadVec.size(); j++, cnt++)
            {
                pid = threadVec[j];

                fd = sys_perf_event_open(&m_attr, pid, cpu, group_fd, 0);

                if (-1 == fd)
                {
                    OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_ERROR, L"sys_perf_event_open failed cpu(%d), pid(%d), cnt(%d)", cpu, pid, cnt);
                }
                else
                {
                    OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_EXTENSIVE, L"for cpu(%d), pid(%d), cnt(%d), fd(%d)", cpu, pid, cnt, fd);
                }

                m_pCountData[cnt].m_fd = fd;

                // If the event is sampling event, get the sample-id
                if (m_samplingEvent)
                {
                    ret = readn(fd, m_pCountData[cnt].m_values, (PERF_MAX_NBR_VALUES * sizeof(uint64_t)));

                    // on error, return
                    if (-1 == ret)
                    {
                        OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_ERROR, L"error in reading samplie-id for event(%d, %lx), fd(%d) errno(%d)",
                                                   m_attr.type, m_attr.config, fd, errno);
                        return E_FAIL;
                    }

                    // If the event is sampling event, get the sample-id
                    // We set the attr::read_format to PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_TOTAL_TIME_RUNNING
                    // | PERF_FORMAT_ID;
                    // for this the format of the data returned by read() on the fd is:
                    //      struct read_format {
                    //         u64      value;
                    //         u64      time_enabled;
                    //         u64      time_running;
                    //         u64      id;
                    //      }
                    //
                    m_pCountData[cnt].m_sampleId =  m_pCountData[cnt].m_values[3];

                    // Now push this into m_eventDataList
                    // TODO: Eventually we will discard pCountData stuff
                    OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_EXTENSIVE, L"push elemnt in m_eventDataList cnt(%d)\n", cnt);
                    m_eventDataList.push_back(m_pCountData[i]);
                }
            } // threads
        } // cpus
    } // per process

    OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_DEBUG, L"size of m_eventDataList (%d)\n", m_eventDataList.size());
    return S_OK;
}
Example #26
0
static int bpf_perf_event_open(int map_fd, int key, int cpu)
{
	struct perf_event_attr attr = {
		.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_TIME,
		.type = PERF_TYPE_SOFTWARE,
		.config = PERF_COUNT_SW_BPF_OUTPUT,
	};
	int pmu_fd;

	pmu_fd = sys_perf_event_open(&attr, -1, cpu, -1, 0);
	if (pmu_fd < 0) {
		p_err("failed to open perf event %d for CPU %d", key, cpu);
		return -1;
	}

	if (bpf_map_update_elem(map_fd, &key, &pmu_fd, BPF_ANY)) {
		p_err("failed to update map for event %d for CPU %d", key, cpu);
		goto err_close;
	}
	if (ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0)) {
		p_err("failed to enable event %d for CPU %d", key, cpu);
		goto err_close;
	}

	return pmu_fd;

err_close:
	close(pmu_fd);
	return -1;
}

int do_event_pipe(int argc, char **argv)
{
	int i, nfds, map_fd, index = -1, cpu = -1;
	struct bpf_map_info map_info = {};
	struct event_ring_info *rings;
	size_t tmp_buf_sz = 0;
	void *tmp_buf = NULL;
	struct pollfd *pfds;
	__u32 map_info_len;
	bool do_all = true;

	map_info_len = sizeof(map_info);
	map_fd = map_parse_fd_and_info(&argc, &argv, &map_info, &map_info_len);
	if (map_fd < 0)
		return -1;

	if (map_info.type != BPF_MAP_TYPE_PERF_EVENT_ARRAY) {
		p_err("map is not a perf event array");
		goto err_close_map;
	}

	while (argc) {
		if (argc < 2)
			BAD_ARG();

		if (is_prefix(*argv, "cpu")) {
			char *endptr;

			NEXT_ARG();
			cpu = strtoul(*argv, &endptr, 0);
			if (*endptr) {
				p_err("can't parse %s as CPU ID", **argv);
				goto err_close_map;
			}

			NEXT_ARG();
		} else if (is_prefix(*argv, "index")) {
			char *endptr;

			NEXT_ARG();
			index = strtoul(*argv, &endptr, 0);
			if (*endptr) {
				p_err("can't parse %s as index", **argv);
				goto err_close_map;
			}

			NEXT_ARG();
		} else {
			BAD_ARG();
		}

		do_all = false;
	}

	if (!do_all) {
		if (index == -1 || cpu == -1) {
			p_err("cpu and index must be specified together");
			goto err_close_map;
		}

		nfds = 1;
	} else {
		nfds = min(get_possible_cpus(), map_info.max_entries);
		cpu = 0;
		index = 0;
	}

	rings = calloc(nfds, sizeof(rings[0]));
	if (!rings)
		goto err_close_map;

	pfds = calloc(nfds, sizeof(pfds[0]));
	if (!pfds)
		goto err_free_rings;

	for (i = 0; i < nfds; i++) {
		rings[i].cpu = cpu + i;
		rings[i].key = index + i;

		rings[i].fd = bpf_perf_event_open(map_fd, rings[i].key,
						  rings[i].cpu);
		if (rings[i].fd < 0)
			goto err_close_fds_prev;

		rings[i].mem = perf_event_mmap(rings[i].fd);
		if (!rings[i].mem)
			goto err_close_fds_current;

		pfds[i].fd = rings[i].fd;
		pfds[i].events = POLLIN;
	}

	signal(SIGINT, int_exit);
	signal(SIGHUP, int_exit);
	signal(SIGTERM, int_exit);

	if (json_output)
		jsonw_start_array(json_wtr);

	while (!stop) {
		poll(pfds, nfds, 200);
		for (i = 0; i < nfds; i++)
			perf_event_read(&rings[i], &tmp_buf, &tmp_buf_sz);
	}
	free(tmp_buf);

	if (json_output)
		jsonw_end_array(json_wtr);

	for (i = 0; i < nfds; i++) {
		perf_event_unmap(rings[i].mem);
		close(rings[i].fd);
	}
	free(pfds);
	free(rings);
	close(map_fd);

	return 0;

err_close_fds_prev:
	while (i--) {
		perf_event_unmap(rings[i].mem);
err_close_fds_current:
		close(rings[i].fd);
	}
	free(pfds);
err_free_rings:
	free(rings);
err_close_map:
	close(map_fd);
	return -1;
}
Example #27
0
static void create_counter(int counter, int cpu, pid_t pid)
{
	char *filter = filters[counter];
	struct perf_event_attr *attr = attrs + counter;
	struct perf_header_attr *h_attr;
	int track = !counter; /* only the first counter needs these */
	int ret;
	struct {
		u64 count;
		u64 time_enabled;
		u64 time_running;
		u64 id;
	} read_data;

	attr->read_format	= PERF_FORMAT_TOTAL_TIME_ENABLED |
				  PERF_FORMAT_TOTAL_TIME_RUNNING |
				  PERF_FORMAT_ID;

	attr->sample_type	|= PERF_SAMPLE_IP | PERF_SAMPLE_TID;

	if (freq) {
		attr->sample_type	|= PERF_SAMPLE_PERIOD;
		attr->freq		= 1;
		attr->sample_freq	= freq;
	}

	if (no_samples)
		attr->sample_freq = 0;

	if (inherit_stat)
		attr->inherit_stat = 1;

	if (sample_address)
		attr->sample_type	|= PERF_SAMPLE_ADDR;

	if (call_graph)
		attr->sample_type	|= PERF_SAMPLE_CALLCHAIN;

	if (raw_samples) {
		attr->sample_type	|= PERF_SAMPLE_TIME;
		attr->sample_type	|= PERF_SAMPLE_RAW;
		attr->sample_type	|= PERF_SAMPLE_CPU;
	}

	attr->mmap		= track;
	attr->comm		= track;
	attr->inherit		= (cpu < 0) && inherit;
	attr->disabled		= 1;

try_again:
	fd[nr_cpu][counter] = sys_perf_event_open(attr, pid, cpu, group_fd, 0);

	if (fd[nr_cpu][counter] < 0) {
		int err = errno;

		if (err == EPERM || err == EACCES)
			die("Permission error - are you root?\n");
		else if (err ==  ENODEV && profile_cpu != -1)
			die("No such device - did you specify an out-of-range profile CPU?\n");

		/*
		 * If it's cycles then fall back to hrtimer
		 * based cpu-clock-tick sw counter, which
		 * is always available even if no PMU support:
		 */
		if (attr->type == PERF_TYPE_HARDWARE
			&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {

			if (verbose)
				warning(" ... trying to fall back to cpu-clock-ticks\n");
			attr->type = PERF_TYPE_SOFTWARE;
			attr->config = PERF_COUNT_SW_CPU_CLOCK;
			goto try_again;
		}
		printf("\n");
		error("perfcounter syscall returned with %d (%s)\n",
			fd[nr_cpu][counter], strerror(err));

#if defined(__i386__) || defined(__x86_64__)
		if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
			die("No hardware sampling interrupt available. No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it.\n");
#endif

		die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
		exit(-1);
	}

	h_attr = get_header_attr(attr, counter);
	if (h_attr == NULL)
		die("nomem\n");

	if (!file_new) {
		if (memcmp(&h_attr->attr, attr, sizeof(*attr))) {
			fprintf(stderr, "incompatible append\n");
			exit(-1);
		}
	}

	if (read(fd[nr_cpu][counter], &read_data, sizeof(read_data)) == -1) {
		perror("Unable to read perf file descriptor\n");
		exit(-1);
	}

	if (perf_header_attr__add_id(h_attr, read_data.id) < 0) {
		pr_warning("Not enough memory to add id\n");
		exit(-1);
	}

	assert(fd[nr_cpu][counter] >= 0);
	fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK);

	/*
	 * First counter acts as the group leader:
	 */
	if (group && group_fd == -1)
		group_fd = fd[nr_cpu][counter];
	if (multiplex && multiplex_fd == -1)
		multiplex_fd = fd[nr_cpu][counter];

	if (multiplex && fd[nr_cpu][counter] != multiplex_fd) {

		ret = ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd);
		assert(ret != -1);
	} else {
		event_array[nr_poll].fd = fd[nr_cpu][counter];
		event_array[nr_poll].events = POLLIN;
		nr_poll++;

		mmap_array[nr_cpu][counter].counter = counter;
		mmap_array[nr_cpu][counter].prev = 0;
		mmap_array[nr_cpu][counter].mask = mmap_pages*page_size - 1;
		mmap_array[nr_cpu][counter].base = mmap(NULL, (mmap_pages+1)*page_size,
				PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter], 0);
		if (mmap_array[nr_cpu][counter].base == MAP_FAILED) {
			error("failed to mmap with %d (%s)\n", errno, strerror(errno));
			exit(-1);
		}
	}

	if (filter != NULL) {
		ret = ioctl(fd[nr_cpu][counter],
			    PERF_EVENT_IOC_SET_FILTER, filter);
		if (ret) {
			error("failed to set filter with %d (%s)\n", errno,
			      strerror(errno));
			exit(-1);
		}
	}

	ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_ENABLE);
}
Example #28
0
int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    QElapsedTimer timer;
    perf_event_attr attr_inst, attr_cpu, attr_miss;

    memset(&attr_inst, 0, sizeof(attr_inst));
    attr_inst.size = sizeof(attr_inst);
    attr_inst.type = PERF_TYPE_HARDWARE;
    attr_inst.config = PERF_COUNT_HW_INSTRUCTIONS;

    memset(&attr_cpu, 0, sizeof(attr_cpu));
    attr_cpu.size = sizeof(attr_cpu);
    attr_cpu.type = PERF_TYPE_SOFTWARE;
    attr_cpu.config = PERF_COUNT_SW_TASK_CLOCK;

    memset(&attr_miss, 0, sizeof(attr_miss));
    attr_miss.size = sizeof(attr_miss);
    attr_miss.type = PERF_TYPE_HW_CACHE;
    attr_miss.config = (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16);

    pid_t tid = gettid();
    int fd_inst = sys_perf_event_open(&attr_inst, tid, -1, -1, 0);
    int fd_cpu = sys_perf_event_open(&attr_cpu, tid, -1, -1, 0);
    int fd_miss = sys_perf_event_open(&attr_cpu, tid, -1, -1, 0);

    int n = 50;
    QVector<Sample> samples(n);

    int sz = 100000;
    QVector<int> idx_rnd(sz); // 100 000 * sizeof(int) = 400 kio, L1 32kio, LLC 4mb
    QVector<int> idx_lin(sz);
    QVector<int> buf_large(sz);
    QVector<int> buf_small(10);
    for (int i = 0; i < sz; i++) {
        idx_rnd[i] = i;
        idx_lin[i] = i;
    }
    std::random_shuffle(idx_rnd.begin(), idx_rnd.end());


    for (int i = 0; i < n; i++) {
        //qDebug() << "before";
        timer.restart();

        qint64 ret = 0;
        qint64 val_inst0, val_inst1;
        qint64 val_cpu0, val_cpu1;
        qint64 val_miss0, val_miss1;

        ret |= read(fd_inst, &val_inst0, sizeof(val_inst0));
        ret |= read(fd_cpu, &val_cpu0, sizeof(val_cpu0));
        ret = read(fd_miss, &val_miss0, sizeof(val_miss0));
        assert(ret > 0);

        bool slow = (i % 6) == 0;
        if (slow) {
//            Tests::read_data(buf_large, idx_rnd);
              Tests::factorial(100);
        } else {
//            Tests::read_data(buf_small, idx_lin);
              Tests::factorial(10);
        }

//        do_compute(work[i % work.size()] * scale);
        ret |= read(fd_inst, &val_inst1, sizeof(val_inst1));
        ret |= read(fd_cpu, &val_cpu1, sizeof(val_cpu1));
        ret |= read(fd_miss, &val_miss1, sizeof(val_miss1));

        qint64 delta = timer.nsecsElapsed() / 1000;
        //qDebug() << "after" << delta;
        samples[i].slow = slow;
        samples[i].delta = delta;
        samples[i].inst = (val_inst1 - val_inst0) / 1000;
        samples[i].cpu = (val_cpu1 - val_cpu0) / 1000;
        samples[i].miss = (val_miss1 - val_miss0);

    }

    //run through all of them:
    for (int i = 0; i < n; i++) {
        Sample s = samples[i];
        qDebug() << s;
    }

    //write the csv:
    QFile file("sample.csv");
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QTextStream out(&file);
        for (const Sample &s: samples) {
            out << s.slow << "," << s.delta << "," << s.inst << "," << s.cpu << "," << s.miss << "\n";
        }
        file.close();
    }

    return 0;
}
Example #29
0
/*
 * Create an event group that contains both a sampled hardware
 * (cpu-cycles) and software (intel_cqm/llc_occupancy/) event. We then
 * wait for the hardware perf counter to overflow and generate a PMI,
 * which triggers an event read for both of the events in the group.
 *
 * Since reading Intel CQM event counters requires sending SMP IPIs, the
 * CQM pmu needs to handle the above situation gracefully, and return
 * the last read counter value to avoid triggering a WARN_ON_ONCE() in
 * smp_call_function_many() caused by sending IPIs from NMI context.
 */
int test__intel_cqm_count_nmi_context(int subtest __maybe_unused)
{
	struct perf_evlist *evlist = NULL;
	struct perf_evsel *evsel = NULL;
	struct perf_event_attr pe;
	int i, fd[2], flag, ret;
	size_t mmap_len;
	void *event;
	pid_t pid;
	int err = TEST_FAIL;

	flag = perf_event_open_cloexec_flag();

	evlist = perf_evlist__new();
	if (!evlist) {
		pr_debug("perf_evlist__new failed\n");
		return TEST_FAIL;
	}

	ret = parse_events(evlist, "intel_cqm/llc_occupancy/", NULL);
	if (ret) {
		pr_debug("parse_events failed, is \"intel_cqm/llc_occupancy/\" available?\n");
		err = TEST_SKIP;
		goto out;
	}

	evsel = perf_evlist__first(evlist);
	if (!evsel) {
		pr_debug("perf_evlist__first failed\n");
		goto out;
	}

	memset(&pe, 0, sizeof(pe));
	pe.size = sizeof(pe);

	pe.type = PERF_TYPE_HARDWARE;
	pe.config = PERF_COUNT_HW_CPU_CYCLES;
	pe.read_format = PERF_FORMAT_GROUP;

	pe.sample_period = 128;
	pe.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_READ;

	pid = spawn();

	fd[0] = sys_perf_event_open(&pe, pid, -1, -1, flag);
	if (fd[0] < 0) {
		pr_debug("failed to open event\n");
		goto out;
	}

	memset(&pe, 0, sizeof(pe));
	pe.size = sizeof(pe);

	pe.type = evsel->attr.type;
	pe.config = evsel->attr.config;

	fd[1] = sys_perf_event_open(&pe, pid, -1, fd[0], flag);
	if (fd[1] < 0) {
		pr_debug("failed to open event\n");
		goto out;
	}

	/*
	 * Pick a power-of-two number of pages + 1 for the meta-data
	 * page (struct perf_event_mmap_page). See tools/perf/design.txt.
	 */
	mmap_len = page_size * 65;

	event = mmap(NULL, mmap_len, PROT_READ, MAP_SHARED, fd[0], 0);
	if (event == (void *)(-1)) {
		pr_debug("failed to mmap %d\n", errno);
		goto out;
	}

	sleep(1);

	err = TEST_OK;

	munmap(event, mmap_len);

	for (i = 0; i < 2; i++)
		close(fd[i]);

	kill(pid, SIGKILL);
	wait(NULL);
out:
	perf_evlist__delete(evlist);
	return err;
}
Example #30
0
void perf_event::create_perf_event(char *eventname, int _cpu)
{
	struct perf_event_attr attr;
	int ret;
	int err;

	struct {
		__u64 count;
		__u64 time_enabled;
		__u64 time_running;
		__u64 id;
	} read_data;

	if (perf_fd != -1)
		clear();

	memset(&attr, 0, sizeof(attr));

	attr.read_format	= PERF_FORMAT_TOTAL_TIME_ENABLED |
				  PERF_FORMAT_TOTAL_TIME_RUNNING |
				  PERF_FORMAT_ID;

	attr.sample_freq	= 0;
	attr.sample_period	= 1;
	attr.sample_type	|= PERF_SAMPLE_RAW | PERF_SAMPLE_CPU | PERF_SAMPLE_TIME;

	attr.mmap		= 1;
	attr.comm		= 1;
	attr.inherit		= 0;
	attr.disabled		= 1;

	attr.type		= PERF_TYPE_TRACEPOINT;
	attr.config		= trace_type;

	if (attr.config <= 0)
		return;

	perf_fd = sys_perf_event_open(&attr, -1, _cpu, -1, 0);

	if (perf_fd < 0) {
		err = errno;
		reset_display();
		if (err == EMFILE)
			fprintf(stderr, _("Too many open files, please increase the limit of open file descriptors.\n"));
		else {
			fprintf(stderr, _("PowerTOP %s needs the kernel to support the 'perf' subsystem\n"), POWERTOP_VERSION);
			fprintf(stderr, _("as well as support for trace points in the kernel:\n"));
			fprintf(stderr, "CONFIG_PERF_EVENTS=y\nCONFIG_PERF_COUNTERS=y\nCONFIG_TRACEPOINTS=y\nCONFIG_TRACING=y\n");
		}
		exit(EXIT_FAILURE);
	}
	if (read(perf_fd, &read_data, sizeof(read_data)) == -1) {
		reset_display();
		perror("Unable to read perf file descriptor\n");
		exit(-1);
	}

	fcntl(perf_fd, F_SETFL, O_NONBLOCK);

	perf_mmap = mmap(NULL, (bufsize+1)*getpagesize(),
				PROT_READ | PROT_WRITE, MAP_SHARED, perf_fd, 0);
	if (perf_mmap == MAP_FAILED) {
		fprintf(stderr, "failed to mmap with %d (%s)\n", errno, strerror(errno));
		return;
	}

	ret = ioctl(perf_fd, PERF_EVENT_IOC_ENABLE, 0);

	if (ret < 0) {
		fprintf(stderr, "failed to enable perf \n");
	}

	pc = (perf_event_mmap_page *)perf_mmap;
	data_mmap = (unsigned char *)perf_mmap + getpagesize();


}