/cpufreq/src/cpufreq-monitor-sysfs.c

https://github.com/mate-desktop/mate-applets · C · 345 lines · 245 code · 70 blank · 30 comment · 26 complexity · 1464837363ee2c20f92e995eca8edebd MD5 · raw file

  1. /*
  2. * MATE CPUFreq Applet
  3. * Copyright (C) 2004 Carlos Garcia Campos <carlosgc@gnome.org>
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * This library 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 GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public
  16. * License along with this library; if not, write to the Free
  17. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  18. *
  19. * Authors : Carlos García Campos <carlosgc@gnome.org>
  20. */
  21. #include <glib.h>
  22. #include <glib/gi18n.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include "cpufreq-monitor-sysfs.h"
  26. #include "cpufreq-utils.h"
  27. enum {
  28. SCALING_MAX,
  29. SCALING_MIN,
  30. GOVERNOR,
  31. CPUINFO_MAX,
  32. SCALING_SETSPEED,
  33. SCALING_CUR_FREQ,
  34. N_FILES
  35. };
  36. static gboolean cpufreq_monitor_sysfs_run (CPUFreqMonitor *monitor);
  37. static GList *cpufreq_monitor_sysfs_get_available_frequencies (CPUFreqMonitor *monitor);
  38. static GList *cpufreq_monitor_sysfs_get_available_governors (CPUFreqMonitor *monitor);
  39. static gchar *cpufreq_sysfs_read (const gchar *path,
  40. GError **error);
  41. /* /sys/devices/system/cpu/cpu[0]/cpufreq/scaling_max_freq
  42. * /sys/devices/system/cpu/cpu[0]/cpufreq/scaling_min_freq
  43. * /sys/devices/system/cpu/cpu[0]/cpufreq/scaling_governor
  44. * /sys/devices/system/cpu/cpu[0]/cpufreq/cpuinfo_max_freq
  45. * /sys/devices/system/cpu/cpu[0]/cpufreq/scaling_setspeed (userspace)
  46. * /sys/devices/system/cpu/cpu[0]/cpufreq/scaling_cur_freq (new governors)
  47. */
  48. const gchar *monitor_sysfs_files[] = {
  49. "scaling_max_freq",
  50. "scaling_min_freq",
  51. "scaling_governor",
  52. "cpuinfo_max_freq",
  53. "scaling_setspeed",
  54. "scaling_cur_freq",
  55. NULL
  56. };
  57. #define CPUFREQ_SYSFS_BASE_PATH "/sys/devices/system/cpu/cpu%u/cpufreq/%s"
  58. G_DEFINE_TYPE (CPUFreqMonitorSysfs, cpufreq_monitor_sysfs, CPUFREQ_TYPE_MONITOR)
  59. static void
  60. cpufreq_monitor_sysfs_init (CPUFreqMonitorSysfs *monitor)
  61. {
  62. }
  63. static GObject *
  64. cpufreq_monitor_sysfs_constructor (GType type,
  65. guint n_construct_properties,
  66. GObjectConstructParam *construct_params)
  67. {
  68. GObject *object;
  69. gchar *path;
  70. gchar *frequency;
  71. gint max_freq;
  72. guint cpu;
  73. GError *error = NULL;
  74. object =
  75. G_OBJECT_CLASS (cpufreq_monitor_sysfs_parent_class)
  76. ->constructor (type,
  77. n_construct_properties,
  78. construct_params);
  79. g_object_get (G_OBJECT (object),
  80. "cpu", &cpu,
  81. NULL);
  82. path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH,
  83. cpu, monitor_sysfs_files[CPUINFO_MAX]);
  84. frequency = cpufreq_sysfs_read (path, &error);
  85. if (!frequency) {
  86. g_warning ("%s", error->message);
  87. g_error_free (error);
  88. max_freq = -1;
  89. } else {
  90. max_freq = atoi (frequency);
  91. }
  92. g_free (path);
  93. g_free (frequency);
  94. g_object_set (G_OBJECT (object),
  95. "max-frequency", max_freq,
  96. NULL);
  97. return object;
  98. }
  99. static void
  100. cpufreq_monitor_sysfs_class_init (CPUFreqMonitorSysfsClass *klass)
  101. {
  102. GObjectClass *object_class = G_OBJECT_CLASS (klass);
  103. CPUFreqMonitorClass *monitor_class = CPUFREQ_MONITOR_CLASS (klass);
  104. object_class->constructor = cpufreq_monitor_sysfs_constructor;
  105. monitor_class->run = cpufreq_monitor_sysfs_run;
  106. monitor_class->get_available_frequencies = cpufreq_monitor_sysfs_get_available_frequencies;
  107. monitor_class->get_available_governors = cpufreq_monitor_sysfs_get_available_governors;
  108. }
  109. CPUFreqMonitor *
  110. cpufreq_monitor_sysfs_new (guint cpu)
  111. {
  112. CPUFreqMonitorSysfs *monitor;
  113. monitor = g_object_new (CPUFREQ_TYPE_MONITOR_SYSFS,
  114. "cpu", cpu, NULL);
  115. return CPUFREQ_MONITOR (monitor);
  116. }
  117. static gchar *
  118. cpufreq_sysfs_read (const gchar *path,
  119. GError **error)
  120. {
  121. gchar *buffer = NULL;
  122. if (!cpufreq_file_get_contents (path, &buffer, NULL, error)) {
  123. return NULL;
  124. }
  125. return g_strchomp (buffer);
  126. }
  127. static gboolean
  128. cpufreq_sysfs_cpu_is_online (guint cpu)
  129. {
  130. gchar *path;
  131. gboolean retval;
  132. path = g_strdup_printf ("/sys/devices/system/cpu/cpu%u/", cpu);
  133. retval = g_file_test (path, G_FILE_TEST_IS_DIR);
  134. g_free (path);
  135. return retval;
  136. }
  137. static gboolean
  138. cpufreq_monitor_sysfs_run (CPUFreqMonitor *monitor)
  139. {
  140. guint cpu;
  141. gchar *frequency;
  142. gchar *governor;
  143. gchar *path;
  144. GError *error = NULL;
  145. g_object_get (G_OBJECT (monitor),
  146. "cpu", &cpu,
  147. NULL);
  148. path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH,
  149. cpu, monitor_sysfs_files[GOVERNOR]);
  150. governor = cpufreq_sysfs_read (path, &error);
  151. if (!governor) {
  152. gboolean retval = FALSE;
  153. /* Check whether it failed because
  154. * cpu is not online.
  155. */
  156. if (!cpufreq_sysfs_cpu_is_online (cpu)) {
  157. g_object_set (G_OBJECT (monitor), "online", FALSE, NULL);
  158. retval = TRUE;
  159. } else {
  160. g_warning ("%s", error->message);
  161. }
  162. g_error_free (error);
  163. g_free (path);
  164. return retval;
  165. }
  166. g_free (path);
  167. if (g_ascii_strcasecmp (governor, "userspace") == 0) {
  168. path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH,
  169. cpu, monitor_sysfs_files[SCALING_SETSPEED]);
  170. } else if (g_ascii_strcasecmp (governor, "powersave") == 0) {
  171. path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH,
  172. cpu, monitor_sysfs_files[SCALING_MIN]);
  173. } else if (g_ascii_strcasecmp (governor, "performance") == 0) {
  174. path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH,
  175. cpu, monitor_sysfs_files[SCALING_MAX]);
  176. } else { /* Ondemand, Conservative, ... */
  177. path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH,
  178. cpu, monitor_sysfs_files[SCALING_CUR_FREQ]);
  179. }
  180. frequency = cpufreq_sysfs_read (path, &error);
  181. if (!frequency) {
  182. g_warning ("%s", error->message);
  183. g_error_free (error);
  184. g_free (path);
  185. g_free (governor);
  186. return FALSE;
  187. }
  188. g_free (path);
  189. g_object_set (G_OBJECT (monitor),
  190. "online", TRUE,
  191. "governor", governor,
  192. "frequency", atoi (frequency),
  193. NULL);
  194. g_free (governor);
  195. g_free (frequency);
  196. return TRUE;
  197. }
  198. static gint
  199. compare (gconstpointer a, gconstpointer b)
  200. {
  201. gint aa, bb;
  202. aa = atoi ((gchar *) a);
  203. bb = atoi ((gchar *) b);
  204. if (aa == bb)
  205. return 0;
  206. else if (aa > bb)
  207. return -1;
  208. else
  209. return 1;
  210. }
  211. static GList *
  212. cpufreq_monitor_sysfs_get_available_frequencies (CPUFreqMonitor *monitor)
  213. {
  214. gchar *path;
  215. GList *list = NULL;
  216. gchar **frequencies = NULL;
  217. gint i;
  218. guint cpu;
  219. gchar *buffer = NULL;
  220. GError *error = NULL;
  221. g_object_get (G_OBJECT (monitor),
  222. "cpu", &cpu, NULL);
  223. path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH, cpu,
  224. "scaling_available_frequencies");
  225. if (!cpufreq_file_get_contents (path, &buffer, NULL, &error)) {
  226. g_warning ("%s", error->message);
  227. g_error_free (error);
  228. g_free (path);
  229. return NULL;
  230. }
  231. g_free (path);
  232. buffer = g_strchomp (buffer);
  233. frequencies = g_strsplit (buffer, " ", -1);
  234. i = 0;
  235. while (frequencies[i]) {
  236. if (!g_list_find_custom (list, frequencies[i], compare))
  237. list = g_list_prepend (list, g_strdup (frequencies[i]));
  238. i++;
  239. }
  240. g_strfreev (frequencies);
  241. g_free (buffer);
  242. return g_list_sort (list, compare);
  243. }
  244. static GList *
  245. cpufreq_monitor_sysfs_get_available_governors (CPUFreqMonitor *monitor)
  246. {
  247. gchar *path;
  248. GList *list = NULL;
  249. gchar **governors = NULL;
  250. gint i;
  251. guint cpu;
  252. gchar *buffer = NULL;
  253. GError *error = NULL;
  254. g_object_get (G_OBJECT (monitor),
  255. "cpu", &cpu, NULL);
  256. path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH, cpu,
  257. "scaling_available_governors");
  258. if (!cpufreq_file_get_contents (path, &buffer, NULL, &error)) {
  259. g_warning ("%s", error->message);
  260. g_error_free (error);
  261. g_free (path);
  262. return NULL;
  263. }
  264. g_free (path);
  265. buffer = g_strchomp (buffer);
  266. governors = g_strsplit (buffer, " ", -1);
  267. i = 0;
  268. while (governors[i] != NULL) {
  269. list = g_list_prepend (list, g_strdup (governors[i]));
  270. i++;
  271. }
  272. g_strfreev (governors);
  273. g_free (buffer);
  274. return list;
  275. }