I'm trying to access the PMU Hardware Performance Counter Details, mainly focusing on CPu-cycles. Below is the C code for it.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <linux/hw_breakpoint.h>
#include <asm/unistd.h>
#include <errno.h>
#include <stdint.h>
#include <inttypes.h>
#include <time.h>
static long
perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
int cpu, int group_fd, unsigned long flags)
{
int ret;
ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
group_fd, flags);
return ret;
}
int
main(int argc, char **argv)
{
int s = 1;
struct perf_event_attr pe1,pe2;
long long count1,count2;
int fd1,fd2;
struct timespec time, time2;
time.tv_sec = 0;
time.tv_nsec = 100000000000;
long pid = strtol(argv[1],NULL,10);
printf("pid : %ld \n",pid);
memset(&pe1, 0, sizeof(struct perf_event_attr));
pe1.type = PERF_TYPE_HARDWARE;
pe1.size = sizeof(struct perf_event_attr);
pe1.config = PERF_COUNT_HW_INSTRUCTIONS;
memset(&pe2, 0, sizeof(struct perf_event_attr));
pe2.type = PERF_TYPE_HARDWARE;
pe2.size = sizeof(struct perf_event_attr);
pe2.config = PERF_COUNT_HW_CACHE_MISSES;
fd1 = perf_event_open(&pe1, pid, -1, -1, 0);
if (fd1 == -1) {
fprintf(stderr, "Error opening leader %llx\n", pe1.config);
exit(EXIT_FAILURE);
}
fd2 = perf_event_open(&pe2, pid, -1, -1, 0);
if (fd2 == -1) {
fprintf(stderr, "Error opening leader %llx\n", pe2.config);
exit(EXIT_FAILURE);
}
while(s<=3){
read(fd1, &count1, sizeof(long long));
printf("cpu cycles : %lld \n", count1);
read(fd2, &count2, sizeof(long long));
printf("cache misses : %lld \n", count2);
nanosleep(&time, &time2);
s++;
}
close(fd1);
close(fd2);
}
When I run the above code by compiling it as gcc code1.c -o code1 and run it by passing the pid as the argument as ./code1 , I get the following output
pid : 5367
cpu cycles : 0
cache misses : 0
cpu cycles : 0
cache misses : 0
cpu cycles : 0
cache misses : 0
.This is the same case for most of the pid's in my system. Does this mean all the pid's are not using any cpu cycles?? Does it mean the the cycles are not counted for that particular PID?
I have edited the code as per your inputs of Ioctl commands, but I'm not sure if this is the way it has to be done.
Here is the code
static long
perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
int cpu, int group_fd, unsigned long flags)
{
int ret;
ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
group_fd, flags);
return ret;
}
int
main(int argc, char **argv)
{
int s = 1;
struct perf_event_attr pe1,pe2;
long long count1,count2;
int fd1,fd2;
struct timespec time, time2;
time.tv_sec = 2;
time.tv_nsec = 100000000000;
long pid = strtol(argv[1],NULL,10);
printf("pid : %ld \n",pid);
memset(&pe1, 0, sizeof(struct perf_event_attr));
pe1.type = PERF_TYPE_HARDWARE;
pe1.size = sizeof(struct perf_event_attr);
pe1.config = PERF_COUNT_HW_CPU_CYCLES;
memset(&pe2, 0, sizeof(struct perf_event_attr));
pe2.type = PERF_TYPE_HARDWARE;
pe2.size = sizeof(struct perf_event_attr);
pe2.config = PERF_COUNT_HW_CACHE_MISSES;
fd1 = perf_event_open(&pe1, pid, -1, -1, 0);
if (fd1 == -1) {
fprintf(stderr, "Error opening leader %llx\n", pe1.config);
exit(EXIT_FAILURE);
}
ioctl(fd1, PERF_EVENT_IOC_RESET, 0);
ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);
ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
read(fd1, &count1, sizeof(long long));
printf("hardware instructions : %lld \n", count1);
fd2 = perf_event_open(&pe2, pid, -1, -1, 0);
if (fd2 == -1) {
fprintf(stderr, "Error opening leader %llx\n", pe2.config);
exit(EXIT_FAILURE);
}
ioctl(fd2, PERF_EVENT_IOC_RESET, 0);
ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);
ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
read(fd2, &count2, sizeof(long long));
printf("cache-misses : %lld \n", count2);
close(fd1);
close(fd2);
}
But I still get 0.
pid : 5
hardware instructions : 0
cache-misses : 0
Am I understanding the concept wrong ??
THe code from this link works fine giving the stats [link] perf_event_open - how to monitoring multiple events.
But I would like to pass PID and check it .