scx_cpu0.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Copyright (c) 2025 Meta Platforms, Inc. and affiliates.
  4. * Copyright (c) 2025 Tejun Heo <tj@kernel.org>
  5. */
  6. #include <stdio.h>
  7. #include <unistd.h>
  8. #include <signal.h>
  9. #include <assert.h>
  10. #include <libgen.h>
  11. #include <bpf/bpf.h>
  12. #include <scx/common.h>
  13. #include "scx_cpu0.bpf.skel.h"
  14. const char help_fmt[] =
  15. "A cpu0 sched_ext scheduler.\n"
  16. "\n"
  17. "See the top-level comment in .bpf.c for more details.\n"
  18. "\n"
  19. "Usage: %s [-v]\n"
  20. "\n"
  21. " -v Print libbpf debug messages\n"
  22. " -h Display this help and exit\n";
  23. static bool verbose;
  24. static volatile int exit_req;
  25. static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
  26. {
  27. if (level == LIBBPF_DEBUG && !verbose)
  28. return 0;
  29. return vfprintf(stderr, format, args);
  30. }
  31. static void sigint_handler(int sig)
  32. {
  33. exit_req = 1;
  34. }
  35. static void read_stats(struct scx_cpu0 *skel, __u64 *stats)
  36. {
  37. int nr_cpus = libbpf_num_possible_cpus();
  38. assert(nr_cpus > 0);
  39. __u64 cnts[2][nr_cpus];
  40. __u32 idx;
  41. memset(stats, 0, sizeof(stats[0]) * 2);
  42. for (idx = 0; idx < 2; idx++) {
  43. int ret, cpu;
  44. ret = bpf_map_lookup_elem(bpf_map__fd(skel->maps.stats),
  45. &idx, cnts[idx]);
  46. if (ret < 0)
  47. continue;
  48. for (cpu = 0; cpu < nr_cpus; cpu++)
  49. stats[idx] += cnts[idx][cpu];
  50. }
  51. }
  52. int main(int argc, char **argv)
  53. {
  54. struct scx_cpu0 *skel;
  55. struct bpf_link *link;
  56. __u32 opt;
  57. __u64 ecode;
  58. libbpf_set_print(libbpf_print_fn);
  59. signal(SIGINT, sigint_handler);
  60. signal(SIGTERM, sigint_handler);
  61. restart:
  62. optind = 1;
  63. skel = SCX_OPS_OPEN(cpu0_ops, scx_cpu0);
  64. skel->rodata->nr_cpus = libbpf_num_possible_cpus();
  65. while ((opt = getopt(argc, argv, "vh")) != -1) {
  66. switch (opt) {
  67. case 'v':
  68. verbose = true;
  69. break;
  70. default:
  71. fprintf(stderr, help_fmt, basename(argv[0]));
  72. return opt != 'h';
  73. }
  74. }
  75. SCX_OPS_LOAD(skel, cpu0_ops, scx_cpu0, uei);
  76. link = SCX_OPS_ATTACH(skel, cpu0_ops, scx_cpu0);
  77. while (!exit_req && !UEI_EXITED(skel, uei)) {
  78. __u64 stats[2];
  79. read_stats(skel, stats);
  80. printf("local=%llu cpu0=%llu\n", stats[0], stats[1]);
  81. fflush(stdout);
  82. sleep(1);
  83. }
  84. bpf_link__destroy(link);
  85. ecode = UEI_REPORT(skel, uei);
  86. scx_cpu0__destroy(skel);
  87. if (UEI_ECODE_RESTART(ecode))
  88. goto restart;
  89. return 0;
  90. }