time_in_state.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /*
  2. * time_in_state eBPF program
  3. *
  4. * Copyright (C) 2018 Google
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License version
  8. * 2 as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. */
  16. #include <bpf_helpers.h>
  17. typedef struct {
  18. uint32_t uid;
  19. uint32_t freq;
  20. } time_key;
  21. DEFINE_BPF_MAP(uid_times_map, PERCPU_HASH, time_key, uint64_t, 10240)
  22. DEFINE_BPF_MAP(cpu_last_update_map, PERCPU_ARRAY, uint32_t, uint64_t, 1)
  23. /* Assume max of 1024 CPUs */
  24. DEFINE_BPF_MAP(cpu_freq_map, ARRAY, uint32_t, uint32_t, 1024)
  25. struct switch_args {
  26. unsigned long long ignore;
  27. char prev_comm[16];
  28. int prev_pid;
  29. int prev_prio;
  30. long long prev_state;
  31. char next_comm[16];
  32. int next_pid;
  33. int next_prio;
  34. };
  35. SEC("tracepoint/sched/sched_switch")
  36. int tp_sched_switch(struct switch_args* args) {
  37. uint32_t zero = 0;
  38. uint64_t* last = bpf_cpu_last_update_map_lookup_elem(&zero);
  39. if (!last) return 0;
  40. uint64_t old_last = *last;
  41. uint64_t time = bpf_ktime_get_ns();
  42. *last = time;
  43. uint32_t cpu = bpf_get_smp_processor_id();
  44. uint32_t* freq = bpf_cpu_freq_map_lookup_elem(&cpu);
  45. if (args->prev_pid && old_last && freq && *freq) {
  46. uint32_t uid = bpf_get_current_uid_gid();
  47. time_key key = {.uid = uid, .freq = *freq};
  48. uint64_t* tot_time = bpf_uid_times_map_lookup_elem(&key);
  49. uint64_t delta = time - old_last;
  50. if (!tot_time)
  51. bpf_uid_times_map_update_elem(&key, &delta, BPF_ANY);
  52. else
  53. *tot_time += delta;
  54. }
  55. return 0;
  56. }
  57. struct cpufreq_args {
  58. unsigned long long ignore;
  59. unsigned int state;
  60. unsigned int cpu_id;
  61. };
  62. SEC("tracepoint/power/cpu_frequency")
  63. int tp_cpufreq(struct cpufreq_args* args) {
  64. uint32_t cpu = args->cpu_id;
  65. unsigned int new = args->state;
  66. bpf_cpu_freq_map_update_elem(&cpu, &new, BPF_ANY);
  67. return 0;
  68. }
  69. char _license[] SEC("license") = "GPL";