cloexec.c 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. #include "util.h"
  2. #include "../perf.h"
  3. #include "cloexec.h"
  4. #include "asm/bug.h"
  5. static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
  6. static int perf_flag_probe(void)
  7. {
  8. /* use 'safest' configuration as used in perf_evsel__fallback() */
  9. struct perf_event_attr attr = {
  10. .type = PERF_COUNT_SW_CPU_CLOCK,
  11. .config = PERF_COUNT_SW_CPU_CLOCK,
  12. };
  13. int fd;
  14. int err;
  15. /* check cloexec flag */
  16. fd = sys_perf_event_open(&attr, 0, -1, -1,
  17. PERF_FLAG_FD_CLOEXEC);
  18. err = errno;
  19. if (fd >= 0) {
  20. close(fd);
  21. return 1;
  22. }
  23. WARN_ONCE(err != EINVAL,
  24. "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
  25. err, strerror(err));
  26. /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
  27. fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
  28. err = errno;
  29. if (WARN_ONCE(fd < 0,
  30. "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
  31. err, strerror(err)))
  32. return -1;
  33. close(fd);
  34. return 0;
  35. }
  36. unsigned long perf_event_open_cloexec_flag(void)
  37. {
  38. static bool probed;
  39. if (!probed) {
  40. if (perf_flag_probe() <= 0)
  41. flag = 0;
  42. probed = true;
  43. }
  44. return flag;
  45. }