title: perf_event_open - how to monitoring multiple events
body: <p>does anyone know how to set <code>perf_event_attr</code> struct that can trigger PMU to monitoring multiple (type) event via <code>perf_event_open()</code>?</p>
  
  <p>Like <code>perf record -e cycles,faults ls</code>, it has two different event type (PERF_TYPE_HARDWARE and PERF_TYPE_SOFTWARE), but in example on <a href="http://www.man7.org/linux/man-pages/man2/perf_event_open.2.html" rel="noreferrer">perf_event_open's manpage</a>, <code>perf_event_attr.type</code> can only assigned single value.</p>
  
  <p>Any suggestion will be appreciate, thanks! </p>
  
  <p><strong>20170208 Update</strong>
  Thanks for @gudok pointing me a direction, but the result seems some abnormal.
  Demo program as below (for measure whole system's CPU cycle and cache miss):</p>
  
  <pre><code>#define _GNU_SOURCE
  #include &lt;stdlib.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;sys/syscall.h&gt;
  #include &lt;string.h&gt;
  #include &lt;sys/ioctl.h&gt;
  #include &lt;linux/perf_event.h&gt;
  #include &lt;linux/hw_breakpoint.h&gt;
  #include &lt;asm/unistd.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;stdint.h&gt;
  #include &lt;inttypes.h&gt;
  #include &lt;time.h&gt;
  
  struct read_format {
    uint64_t nr;
    struct {
      uint64_t value;
      uint64_t id;
    } values[];
  };
  
  int main(int argc, char* argv[]) {
    struct perf_event_attr pea;
    int fd1, fd2;
    uint64_t id1, id2;
    uint64_t val1, val2;
    char buf[4096];
    struct read_format* rf = (struct read_format*) buf;
    int i,j;
    struct timespec time, time2;
  
    time.tv_sec = 1;
    time.tv_nsec = 0;
  
    memset(&amp;pea, 0, sizeof(struct perf_event_attr));
    pea.type = PERF_TYPE_HARDWARE;
    pea.size = sizeof(struct perf_event_attr);
    pea.config = PERF_COUNT_HW_CPU_CYCLES;
    pea.disabled = 1;
    pea.exclude_kernel = 1;
    pea.exclude_hv = 1;
    pea.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
    fd1 = syscall(__NR_perf_event_open, &amp;pea, 0, -1, -1, 0);
    ioctl(fd1, PERF_EVENT_IOC_ID, &amp;id1);
  
    memset(&amp;pea, 0, sizeof(struct perf_event_attr));
    pea.type = PERF_TYPE_HARDWARE;
    pea.size = sizeof(struct perf_event_attr);
    pea.config = PERF_COUNT_HW_CACHE_MISSES;
    pea.disabled = 1;
    pea.exclude_kernel = 1;
    pea.exclude_hv = 1;
    pea.precise_ip = 2;  // want to using PEBS 
    pea.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
    fd2 = syscall(__NR_perf_event_open, &amp;pea, 0, -1, fd1 /*!!!*/, 0);
    ioctl(fd2, PERF_EVENT_IOC_ID, &amp;id2);
  
    ioctl(fd1, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP);
    ioctl(fd1, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP);
    while (1) {
      nanosleep(&amp;time, &amp;time2);
  
      //ioctl(fd1, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP);
  
      read(fd1, buf, sizeof(buf));
      for (i = 0; i &lt; rf-&gt;nr; i++) {
        if (rf-&gt;values[i].id == id1) {
          val1 = rf-&gt;values[i].value;
        } else if (rf-&gt;values[i].id == id2) {
          val2 = rf-&gt;values[i].value;
        }
      }
  
      printf("cpu cycles: %"PRIu64"\n", val1);
      printf("cache misses: %"PRIu64"\n", val2);
  
    }
  
    return 0;
  }
  </code></pre>
  
  <p>And the output is:</p>
  
  <pre><code>cpu cycles: 120   // Just have about 120 CPU cycles in a second
  cache misses: 0   // and doesn't have any cache miss?
  cpu cycles: 233
  cache misses: 0
  cpu cycles: 352
  cache misses: 0
  cpu cycles: 455
  cache misses: 0
  cpu cycles: 562
  cache misses: 0
  cpu cycles: 673
  cache misses: 0
  cpu cycles: 794
  cache misses: 0
  cpu cycles: 907
  cache misses: 0
  cpu cycles: 1011
  cache misses: 0
  cpu cycles: 1129
  cache misses: 3
  cpu cycles: 1269
  cache misses: 4
  cpu cycles: 1423
  </code></pre>