openat-syscall-all-cpus.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <errno.h>
  3. #include <inttypes.h>
  4. /* For the CPU_* macros */
  5. #include <pthread.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <fcntl.h>
  9. #include <api/fs/fs.h>
  10. #include <linux/err.h>
  11. #include <linux/string.h>
  12. #include <api/fs/tracing_path.h>
  13. #include "evsel.h"
  14. #include "tests.h"
  15. #include "thread_map.h"
  16. #include <perf/cpumap.h>
  17. #include <internal/cpumap.h>
  18. #include "debug.h"
  19. #include "stat.h"
  20. #include "util/counts.h"
  21. int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int subtest __maybe_unused)
  22. {
  23. int err = -1, fd, cpu;
  24. struct perf_cpu_map *cpus;
  25. struct evsel *evsel;
  26. unsigned int nr_openat_calls = 111, i;
  27. cpu_set_t cpu_set;
  28. struct perf_thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
  29. char sbuf[STRERR_BUFSIZE];
  30. char errbuf[BUFSIZ];
  31. if (threads == NULL) {
  32. pr_debug("thread_map__new\n");
  33. return -1;
  34. }
  35. cpus = perf_cpu_map__new(NULL);
  36. if (cpus == NULL) {
  37. pr_debug("perf_cpu_map__new\n");
  38. goto out_thread_map_delete;
  39. }
  40. CPU_ZERO(&cpu_set);
  41. evsel = evsel__newtp("syscalls", "sys_enter_openat");
  42. if (IS_ERR(evsel)) {
  43. tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat");
  44. pr_debug("%s\n", errbuf);
  45. goto out_cpu_map_delete;
  46. }
  47. if (evsel__open(evsel, cpus, threads) < 0) {
  48. pr_debug("failed to open counter: %s, "
  49. "tweak /proc/sys/kernel/perf_event_paranoid?\n",
  50. str_error_r(errno, sbuf, sizeof(sbuf)));
  51. goto out_evsel_delete;
  52. }
  53. for (cpu = 0; cpu < cpus->nr; ++cpu) {
  54. unsigned int ncalls = nr_openat_calls + cpu;
  55. /*
  56. * XXX eventually lift this restriction in a way that
  57. * keeps perf building on older glibc installations
  58. * without CPU_ALLOC. 1024 cpus in 2010 still seems
  59. * a reasonable upper limit tho :-)
  60. */
  61. if (cpus->map[cpu] >= CPU_SETSIZE) {
  62. pr_debug("Ignoring CPU %d\n", cpus->map[cpu]);
  63. continue;
  64. }
  65. CPU_SET(cpus->map[cpu], &cpu_set);
  66. if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
  67. pr_debug("sched_setaffinity() failed on CPU %d: %s ",
  68. cpus->map[cpu],
  69. str_error_r(errno, sbuf, sizeof(sbuf)));
  70. goto out_close_fd;
  71. }
  72. for (i = 0; i < ncalls; ++i) {
  73. fd = openat(0, "/etc/passwd", O_RDONLY);
  74. close(fd);
  75. }
  76. CPU_CLR(cpus->map[cpu], &cpu_set);
  77. }
  78. /*
  79. * Here we need to explicitly preallocate the counts, as if
  80. * we use the auto allocation it will allocate just for 1 cpu,
  81. * as we start by cpu 0.
  82. */
  83. if (evsel__alloc_counts(evsel, cpus->nr, 1) < 0) {
  84. pr_debug("evsel__alloc_counts(ncpus=%d)\n", cpus->nr);
  85. goto out_close_fd;
  86. }
  87. err = 0;
  88. for (cpu = 0; cpu < cpus->nr; ++cpu) {
  89. unsigned int expected;
  90. if (cpus->map[cpu] >= CPU_SETSIZE)
  91. continue;
  92. if (evsel__read_on_cpu(evsel, cpu, 0) < 0) {
  93. pr_debug("evsel__read_on_cpu\n");
  94. err = -1;
  95. break;
  96. }
  97. expected = nr_openat_calls + cpu;
  98. if (perf_counts(evsel->counts, cpu, 0)->val != expected) {
  99. pr_debug("evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n",
  100. expected, cpus->map[cpu], perf_counts(evsel->counts, cpu, 0)->val);
  101. err = -1;
  102. }
  103. }
  104. evsel__free_counts(evsel);
  105. out_close_fd:
  106. perf_evsel__close_fd(&evsel->core);
  107. out_evsel_delete:
  108. evsel__delete(evsel);
  109. out_cpu_map_delete:
  110. perf_cpu_map__put(cpus);
  111. out_thread_map_delete:
  112. perf_thread_map__put(threads);
  113. return err;
  114. }