summaryrefslogtreecommitdiffstats
path: root/datatop/src/datatop_cpu_stats_poll.c
diff options
context:
space:
mode:
Diffstat (limited to 'datatop/src/datatop_cpu_stats_poll.c')
-rw-r--r--datatop/src/datatop_cpu_stats_poll.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/datatop/src/datatop_cpu_stats_poll.c b/datatop/src/datatop_cpu_stats_poll.c
new file mode 100644
index 0000000..275ddd8
--- /dev/null
+++ b/datatop/src/datatop_cpu_stats_poll.c
@@ -0,0 +1,182 @@
+/************************************************************************
+Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+************************************************************************/
+
+/**
+ * @file datatop_cpu_stats_poll.c
+ * @brief Calls dtop_value_only_init for necessary cpu datapoints.
+ *
+ * File contains methods for determing number of cpu's online and calling
+ * correct initialization function to gather scaling_cur_freq data point
+ * for each cpu along with each cpu's online status.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include "datatop_interface.h"
+#include "datatop_fileops.h"
+#include "datatop_str.h"
+#include "datatop_polling.h"
+
+#define DTOP_GEN_SIZE 8192
+#define DTOP_GEN_LINE (DTOP_GEN_SIZE>>2)
+#define NO_CPUS_ONLINE -1
+
+/**
+ * @brief Searches /sys/devices/system/cpu/ directory to get find number of CPUs.
+ *
+ * @return Number of CPUs found in directory.
+ */
+static int dtop_cpu_search(void)
+{
+ DIR *dp;
+ struct dirent *entry;
+ struct stat s;
+ int cpu_amt;
+ char cwd[1024];
+
+ if (!getcwd(cwd, sizeof(cwd))) {
+ fprintf(stderr, "Failed to get current working dir\n");
+ return -1;
+ }
+
+ dp = opendir("/sys/devices/system/cpu/");
+ if (dp == NULL) {
+ fprintf(stderr, "err=%d: %s\n", errno, strerror(errno));
+ fprintf(stderr, "Cannot open directory: %s\n",
+ "/sys/devices/system/cpu/");
+ return NO_CPUS_ONLINE;
+ }
+
+ chdir("/sys/devices/system/cpu/");
+ cpu_amt = 0;
+ while ((entry = readdir(dp))) {
+ if (stat(entry->d_name, &s)) {
+ printf("stat err=%d: %s\n", errno, strerror(errno));
+ return NO_CPUS_ONLINE;
+ }
+
+ if (entry->d_name[0] == 'c' &&
+ entry->d_name[1] == 'p' &&
+ entry->d_name[2] == 'u' &&
+ (isdigit(entry->d_name[3]))) {
+
+ cpu_amt++;
+ }
+ }
+
+ closedir(dp);
+ chdir(cwd);
+ return cpu_amt;
+}
+
+/**
+ * @brief Creates a dpg designed for CPU online and CPU scaling_cur_freq stats.
+ *
+ * @param name Name of file dpg represents.
+ */
+static void construct_cpu_stat_dpg(char *name)
+{
+ char *file = malloc(strlen(name) + 1);
+ struct dtop_data_point *dp =
+ malloc(sizeof(struct dtop_data_point));
+ struct dtop_data_point_gatherer *dpg = malloc
+ (sizeof(struct dtop_data_point_gatherer));
+
+ strlcpy(file, name, strlen(name) + 1);
+
+ dp[0].type = DTOP_ULONG;
+ dp[0].name = malloc(5);
+ strlcpy(dp[0].name, "", 5);
+ dp[0].prefix = NULL;
+ dp[0].data.d_ulong = 0;
+ dp[0].initial_data.d_ulong = 0;
+ dp[0].skip = DO_NOT_SKIP;
+ dp[0].initial_data_populated = NOT_POPULATED;
+
+ dpg->prefix = file;
+ dpg->file = file;
+ dpg->poll = dtop_value_only_poll;
+ dpg->data_points = dp;
+ dpg->data_points_len = 1;
+ dpg->deconstruct = dtop_value_only_dpg_deconstructor;
+
+ dtop_register(dpg);
+}
+
+/**
+ * @brief Calls dpg constructor for necessary CPU stat files.
+ *
+ * Creates file names based on number of CPUs found and calls the
+ * dpg constructor for them.
+ *
+ * @param file Directory where the CPUs are found.
+ * @param add String which is concatenated onto file and represents
+ * the path after a CPU directory is entered.
+ * @param cpu_amt Amount of CPUs found on device.
+ */
+static void cpu_poll_helper(char *file, char *add, int cpu_amt)
+{
+ int i;
+ for (i = 0; i < cpu_amt; i++) {
+ char *cpu_num = malloc(5);
+ char *newfile;
+ int nf_len;
+ snprintf(cpu_num, 5, "%d", i);
+ nf_len = strlen(file) + strlen(add) + strlen(cpu_num) + 2;
+ newfile = malloc(nf_len);
+ strlcpy(newfile, file, nf_len);
+ strlcat(newfile, cpu_num, nf_len);
+ strlcat(newfile, add, nf_len);
+ free(cpu_num);
+ construct_cpu_stat_dpg(newfile);
+ free(newfile);
+ }
+}
+
+/**
+ * @brief Calls necessary functions for CPU stat dpgs.
+ */
+void dtop_cpu_stats_init(void)
+{
+ int cpu_amt;
+ char *file = "/sys/devices/system/cpu/cpu";
+ char *add = "/cpufreq/scaling_cur_freq";
+
+ cpu_amt = dtop_cpu_search();
+ cpu_poll_helper(file, add, cpu_amt);
+ add = "/online";
+ cpu_poll_helper(file, add, cpu_amt);
+}