| /* |
| * 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 <map> |
| #include <utility> |
| |
| #include <stdint.h> |
| #include <string.h> |
| #include <stdio.h> |
| |
| #include "timer.h" |
| #include "../lib.h" |
| #include "process.h" |
| |
| using namespace std; |
| |
| static bool timer_is_deferred(const char *handler) |
| { |
| FILE *file; |
| bool ret = false; |
| char line[4096]; |
| |
| file = fopen("/proc/timer_stats", "r"); |
| if (!file) { |
| return ret; |
| } |
| |
| while (!feof(file)) { |
| if (fgets(line, 4096, file) == NULL) |
| break; |
| if (strstr(line, handler)) { |
| ret = (strstr(line, "D,") != NULL); |
| if (ret == true) |
| break; |
| } |
| } |
| fclose(file); |
| return ret; |
| } |
| |
| timer::timer(unsigned long address) : power_consumer() |
| { |
| strncpy(handler, kernel_function(address), 31); |
| raw_count = 0; |
| deferred = timer_is_deferred(handler); |
| } |
| |
| |
| static map<unsigned long, class timer *> all_timers; |
| static map<unsigned long, uint64_t> running_since; |
| |
| void timer::fire(uint64_t time, uint64_t timer_struct) |
| { |
| running_since[timer_struct] = time; |
| } |
| |
| uint64_t timer::done(uint64_t time, uint64_t timer_struct) |
| { |
| int64_t delta; |
| |
| if (running_since[timer_struct] > time) |
| return 0; |
| |
| delta = time - running_since[timer_struct]; |
| |
| accumulated_runtime += delta; |
| |
| raw_count++; |
| |
| return delta; |
| } |
| |
| double timer::usage_summary(void) |
| { |
| double t; |
| t = (accumulated_runtime - child_runtime) / 1000000.0 / measurement_time / 10; |
| return t; |
| } |
| |
| const char * timer::usage_units_summary(void) |
| { |
| return "%"; |
| } |
| |
| |
| |
| static void add_timer(const pair<unsigned long, class timer*>& elem) |
| { |
| all_power.push_back(elem.second); |
| } |
| |
| void all_timers_to_all_power(void) |
| { |
| for_each(all_timers.begin(), all_timers.end(), add_timer); |
| |
| } |
| |
| |
| const char * timer::description(void) |
| { |
| if (child_runtime > accumulated_runtime) |
| child_runtime = 0; |
| |
| sprintf(desc, "%s", handler); |
| return desc; |
| } |
| |
| |
| class timer * find_create_timer(uint64_t func) |
| { |
| class timer * timer; |
| if (all_timers.find(func) != all_timers.end()) |
| return all_timers[func]; |
| |
| timer = new class timer(func); |
| all_timers[func] = timer; |
| return timer; |
| |
| } |
| |
| void clear_timers(void) |
| { |
| std::map<unsigned long, class timer *>::iterator it = all_timers.begin(); |
| while (it != all_timers.end()) { |
| delete it->second; |
| all_timers.erase(it); |
| it = all_timers.begin(); |
| } |
| } |
| |
| bool timer::is_deferred(void) |
| { |
| return deferred; |
| } |