cpu.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #include <err.h>
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5. #include <sys/param.h> /* MIN, MAX */
  6. #include "cpu.h"
  7. #include "../lib/util.h"
  8. #include "../aslstatus.h"
  9. #include "../components_config.h"
  10. /* clang-format off */
  11. #define CPU_SUM(X) \
  12. (X[CPU_STATE_USER] \
  13. + X[CPU_STATE_NICE] \
  14. + X[CPU_STATE_SYSTEM] \
  15. + X[CPU_STATE_IDLE] \
  16. + X[CPU_STATE_IOWAIT] \
  17. + X[CPU_STATE_IRQ] \
  18. + X[CPU_STATE_SOFTIRQ] \
  19. + X[CPU_STATE_STEAL])
  20. #define CPU_USED(X) \
  21. (X[CPU_STATE_USER] \
  22. + X[CPU_STATE_NICE] \
  23. + X[CPU_STATE_SYSTEM] \
  24. + X[CPU_STATE_IRQ] \
  25. + X[CPU_STATE_SOFTIRQ] \
  26. + X[CPU_STATE_STEAL])
  27. /* clang-format on */
  28. static void cpu_perc_cleanup(void *ptr);
  29. void
  30. cpu_freq(char *out,
  31. const char __unused *_a,
  32. uint32_t __unused _i,
  33. static_data_t *static_data)
  34. {
  35. uintmax_t freq;
  36. int *fd = static_data->data;
  37. char buf[JU_STR_SIZE];
  38. if (!static_data->cleanup) static_data->cleanup = fd_cleanup;
  39. if (!sysfs_fd_or_rewind(fd,
  40. "/sys/devices/system/cpu",
  41. "cpu0",
  42. "cpufreq/scaling_cur_freq"))
  43. ERRRET(out);
  44. if (!eread(*fd, WITH_LEN(buf))) ERRRET(out);
  45. /* in kHz */
  46. if (!esscanf(1, buf, "%ju", &freq)) ERRRET(out);
  47. fmt_human(out, freq * 1000);
  48. }
  49. void
  50. cpu_perc(char *out,
  51. const char __unused *_a,
  52. uint32_t __unused _i,
  53. static_data_t *static_data)
  54. {
  55. struct cpu_data_t *data = static_data->data;
  56. char buf[STR_SIZE("cpu ") + JU_STR_SIZE * LEN(data->states)];
  57. __typeof__(*data->states) old_states[LEN(data->states)], sum;
  58. __typeof__(sum) tmp_sum, old_sum;
  59. if (!static_data->cleanup) static_data->cleanup = cpu_perc_cleanup;
  60. memcpy(old_states, data->states, sizeof(data->states));
  61. if (!sysfs_fd_or_rewind(&data->fd, "/", "proc", "stat")) ERRRET(out);
  62. if (!eread(data->fd, WITH_LEN(buf))) ERRRET(out);
  63. /* cpu user nice system idle iowait irq softirq */
  64. if (!esscanf(LEN(data->states),
  65. buf,
  66. "cpu %ju %ju %ju %ju %ju %ju %ju %ju",
  67. &data->states[CPU_STATE_USER],
  68. &data->states[CPU_STATE_NICE],
  69. &data->states[CPU_STATE_SYSTEM],
  70. &data->states[CPU_STATE_IDLE],
  71. &data->states[CPU_STATE_IOWAIT],
  72. &data->states[CPU_STATE_IRQ],
  73. &data->states[CPU_STATE_SOFTIRQ],
  74. &data->states[CPU_STATE_STEAL]))
  75. ERRRET(out);
  76. if (!old_states[CPU_STATE_USER]) ERRRET(out);
  77. #define ABS_DEC(A, B) (MAX((A), (B)) - MIN((A), (B)))
  78. old_sum = CPU_SUM(old_states);
  79. tmp_sum = CPU_SUM(data->states);
  80. sum = ABS_DEC(old_sum, tmp_sum);
  81. if (!sum) ERRRET(out);
  82. old_sum = CPU_USED(old_states);
  83. tmp_sum = CPU_USED(data->states);
  84. bprintf(out,
  85. "%" PRIperc,
  86. (percent_t)(100 * ABS_DEC(old_sum, tmp_sum) / sum));
  87. }
  88. static inline void
  89. cpu_perc_cleanup(void *ptr)
  90. {
  91. eclose(((struct cpu_data_t *)ptr)->fd);
  92. }