This source file includes following definitions.
- sched_getcpu
- perf_flag_probe
- perf_event_open_cloexec_flag
   1 
   2 #include <errno.h>
   3 #include <sched.h>
   4 #include "util.h" 
   5 #include "../perf-sys.h"
   6 #include "cloexec.h"
   7 #include "event.h"
   8 #include "asm/bug.h"
   9 #include "debug.h"
  10 #include <unistd.h>
  11 #include <sys/syscall.h>
  12 #include <linux/string.h>
  13 
  14 static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
  15 
  16 int __weak sched_getcpu(void)
  17 {
  18 #ifdef __NR_getcpu
  19         unsigned cpu;
  20         int err = syscall(__NR_getcpu, &cpu, NULL, NULL);
  21         if (!err)
  22                 return cpu;
  23 #else
  24         errno = ENOSYS;
  25 #endif
  26         return -1;
  27 }
  28 
  29 static int perf_flag_probe(void)
  30 {
  31         
  32         struct perf_event_attr attr = {
  33                 .type = PERF_TYPE_SOFTWARE,
  34                 .config = PERF_COUNT_SW_CPU_CLOCK,
  35                 .exclude_kernel = 1,
  36         };
  37         int fd;
  38         int err;
  39         int cpu;
  40         pid_t pid = -1;
  41         char sbuf[STRERR_BUFSIZE];
  42 
  43         cpu = sched_getcpu();
  44         if (cpu < 0)
  45                 cpu = 0;
  46 
  47         
  48 
  49 
  50 
  51         while (1) {
  52                 
  53                 fd = sys_perf_event_open(&attr, pid, cpu, -1,
  54                                          PERF_FLAG_FD_CLOEXEC);
  55                 if (fd < 0 && pid == -1 && errno == EACCES) {
  56                         pid = 0;
  57                         continue;
  58                 }
  59                 break;
  60         }
  61         err = errno;
  62 
  63         if (fd >= 0) {
  64                 close(fd);
  65                 return 1;
  66         }
  67 
  68         WARN_ONCE(err != EINVAL && err != EBUSY,
  69                   "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
  70                   err, str_error_r(err, sbuf, sizeof(sbuf)));
  71 
  72         
  73         while (1) {
  74                 fd = sys_perf_event_open(&attr, pid, cpu, -1, 0);
  75                 if (fd < 0 && pid == -1 && errno == EACCES) {
  76                         pid = 0;
  77                         continue;
  78                 }
  79                 break;
  80         }
  81         err = errno;
  82 
  83         if (fd >= 0)
  84                 close(fd);
  85 
  86         if (WARN_ONCE(fd < 0 && err != EBUSY,
  87                       "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
  88                       err, str_error_r(err, sbuf, sizeof(sbuf))))
  89                 return -1;
  90 
  91         return 0;
  92 }
  93 
  94 unsigned long perf_event_open_cloexec_flag(void)
  95 {
  96         static bool probed;
  97 
  98         if (!probed) {
  99                 if (perf_flag_probe() <= 0)
 100                         flag = 0;
 101                 probed = true;
 102         }
 103 
 104         return flag;
 105 }