1

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 .

SRT
  • 41
  • 7

1 Answers1

1

You are missing the ioctl commands that will be needed to enable /disable the counters. Something like this -

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);

Also moreover, the fd1 file descriptor will be involved with counting the number of retired instructions, not the number of cpu-cycles.

Edit

To count the number of HW-cycles, the config should be-

pe1.config = PERF_COUNT_HW_CPU_CYCLES

Arnabjyoti Kalita
  • 2,325
  • 1
  • 18
  • 31
  • Then is there a way to count the cycles ? – SRT Apr 15 '18 at 17:51
  • Hello , I have updated the code but I still get the numbers as 0. Any comments as to why. – SRT Apr 16 '18 at 04:24
  • I unfortunately cannot identify the problem without looking at your code @Susmitha – Arnabjyoti Kalita Apr 17 '18 at 02:53
  • Is this happening for all the PIDs ? Have you looked at the answer to this :- [answer](https://stackoverflow.com/questions/42088515/perf-event-open-how-to-monitoring-multiple-events) – Arnabjyoti Kalita Apr 17 '18 at 19:27
  • Yup I looked at the answer, but did not know where to give thr ioctl statements, hence have just followed the format posted in the answer. – SRT Apr 17 '18 at 21:33