diff options
Diffstat (limited to 'src/process/process.cpp')
-rw-r--r-- | src/process/process.cpp | 246 |
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); + } +} |