summaryrefslogtreecommitdiffstats
path: root/src/process/process.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/process/process.cpp')
-rw-r--r--src/process/process.cpp246
1 files changed, 246 insertions, 0 deletions
diff --git a/src/process/process.cpp b/src/process/process.cpp
new file mode 100644
index 0000000..dad90ba
--- /dev/null
+++ b/src/process/process.cpp
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+
+
+#include "process.h"
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+#include <iterator>
+#include "../lib.h"
+
+
+vector <class process *> all_processes;
+
+void process::account_disk_dirty(void)
+{
+ disk_hits++;
+}
+
+void process::schedule_thread(uint64_t time, int thread_id)
+{
+ running_since = time;
+ running = 1;
+}
+
+
+uint64_t process::deschedule_thread(uint64_t time, int thread_id)
+{
+ uint64_t delta;
+
+ if (!running_since)
+ return 0;
+
+ delta = time - running_since;
+
+ if (time < running_since)
+ printf("%llu time %llu since \n", (unsigned long long)time,
+ (unsigned long long)running_since);
+
+ if (thread_id == 0) /* idle thread */
+ delta = 0;
+ accumulated_runtime += delta;
+ running = 0;
+
+ return delta;
+}
+
+static void cmdline_to_string(std::string& str)
+{
+ std::replace(str.begin(), str.end(), '\0', ' ');
+}
+
+
+process::process(const char *_comm, int _pid, int _tid) : power_consumer()
+{
+ char line[4097];
+ ifstream file;
+ ssize_t pos;
+
+ pt_strcpy(comm, _comm);
+ pid = _pid;
+ is_idle = 0;
+ running = 0;
+ last_waker = NULL;
+ waker = NULL;
+ is_kernel = 0;
+ tgid = _tid;
+
+ if (_tid == 0) {
+ sprintf(line, "/proc/%i/status", _pid);
+ file.open(line);
+ while (file) {
+ file.getline(line, 4096);
+ line[4096] = '\0';
+ if (strstr(line, "Tgid")) {
+ char *c;
+ c = strchr(line, ':');
+ if (!c)
+ continue;
+ c++;
+ tgid = strtoull(c, NULL, 10);
+ break;
+ }
+ }
+ file.close();
+ }
+
+ if (strncmp(_comm, "kondemand/", 10) == 0)
+ is_idle = 1;
+
+ pos = snprintf(desc, sizeof(desc), "[PID %d] ", pid);
+
+ if (pos < 0)
+ pos = 0;
+ if ((size_t)pos > sizeof(desc))
+ return;
+
+ strncpy(desc + pos, comm, sizeof(desc) - pos - 1);
+ desc[sizeof(desc) - 1] = '\0';
+
+ sprintf(line, "/proc/%i/cmdline", _pid);
+ file.open(line, ios::binary);
+ if (file) {
+ std::string cmdline(std::istreambuf_iterator<char>(file), (std::istreambuf_iterator<char>()));
+ file.close();
+ if (cmdline.size() < 1) {
+ is_kernel = 1;
+ snprintf(desc + pos, sizeof(desc) - pos, "[%s]", comm);
+ } else {
+ cmdline_to_string(cmdline);
+ strncpy(desc + pos, cmdline.c_str(), sizeof(desc) - pos - 1);
+ desc[sizeof(desc) - 1] = '\0';
+ }
+ }
+}
+
+const char * process::description(void)
+{
+
+ if (child_runtime > accumulated_runtime)
+ child_runtime = 0;
+
+ return desc;
+}
+
+double process::usage_summary(void)
+{
+ double t;
+ t = (accumulated_runtime - child_runtime) / 1000000.0 / measurement_time / 10;
+ return t;
+}
+
+const char * process::usage_units_summary(void)
+{
+ return "%";
+}
+
+class process * find_create_process(const char *comm, int pid)
+{
+ unsigned int i;
+ class process *new_proc;
+
+ for (i = 0; i < all_processes.size(); i++) {
+ if (all_processes[i]->pid == pid && strcmp(comm, all_processes[i]->comm) == 0)
+ return all_processes[i];
+ }
+
+ new_proc = new class process(comm, pid);
+ all_processes.push_back(new_proc);
+ return new_proc;
+}
+
+class process * find_create_process(char *comm, int pid)
+{
+ return find_create_process((const char*)comm, pid);
+}
+
+static void merge_process(class process *one, class process *two)
+{
+ one->accumulated_runtime += two->accumulated_runtime;
+ one->child_runtime += two->child_runtime;
+ one->wake_ups += two->wake_ups;
+ one->disk_hits += two->disk_hits;
+ one->hard_disk_hits += two->hard_disk_hits;
+ one->xwakes += two->xwakes;
+ one->gpu_ops += two->gpu_ops;
+ one->power_charge += two->power_charge;
+}
+
+
+void merge_processes(void)
+{
+ std::vector<class process*>::iterator it1, it2;
+ class process *one, *two;
+
+ it1 = all_processes.begin();
+ while (it1 != all_processes.end()) {
+ it2 = it1 + 1;
+ one = *it1;
+ while (it2 != all_processes.end()) {
+ two = *it2;
+ /* fold threads */
+ if (one->pid == two->tgid && two->tgid != 0) {
+ merge_process(one, two);
+ delete *it2;
+ it2 = all_processes.erase(it2);
+ continue;
+ }
+ /* find dupes and add up */
+ if (!strcmp(one->desc, two->desc)) {
+ merge_process(one, two);
+ delete *it2;
+ it2 = all_processes.erase(it2);
+ continue;
+ }
+ ++it2;
+ }
+ ++it1;
+ }
+}
+
+void all_processes_to_all_power(void)
+{
+ unsigned int i;
+ for (i = 0; i < all_processes.size() ; i++)
+ if (all_processes[i]->accumulated_runtime ||
+ all_processes[i]->power_charge)
+ all_power.push_back(all_processes[i]);
+}
+
+void clear_processes(void)
+{
+ std::vector <class process *>::iterator it = all_processes.begin();
+ while (it != all_processes.end()) {
+ delete *it;
+ it = all_processes.erase(it);
+ }
+}