2
* thd_rapl_power_meter.cpp: thermal cooling class implementation
4
* Copyright (C) 2014 Intel Corporation. All rights reserved.
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License version
8
* 2 or later as published by the Free Software Foundation.
10
* This program 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
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
* Author Name <Srinivas.Pandruvada@linux.intel.com>
25
#include "thd_rapl_power_meter.h"
30
static void *rapl_periodic_callback(void *data) {
31
cthd_rapl_power_meter *rapl_cl = (cthd_rapl_power_meter*) data;
34
if (!rapl_cl->rapl_energy_loop())
36
sleep(rapl_cl->rapl_callback_timeout);
42
cthd_rapl_power_meter::cthd_rapl_power_meter(unsigned int mask) :
43
rapl_present(true), rapl_sysfs("/sys/class/powercap/intel-rapl/"), domain_list(
44
0), last_time(0), poll_thread(0), measure_mask(mask), enable_measurement(
47
if (rapl_sysfs.exists()) {
48
thd_log_debug("RAPL sysfs present \n");
50
last_time = time(NULL);
51
rapl_read_domains(rapl_sysfs.get_base_path());
53
thd_log_warn("NO RAPL sysfs present \n");
58
void cthd_rapl_power_meter::rapl_read_domains(const char *dir_name) {
64
struct dirent *dir_entry;
66
thd_log_debug("RAPL base path %s\n", dir_name);
67
if ((dir = opendir(dir_name)) != NULL) {
68
while ((dir_entry = readdir(dir)) != NULL) {
70
std::stringstream path;
75
domain.energy_counter = 0;
76
domain.energy_cumulative_counter = 0;
77
domain.max_energy_range = 0;
78
domain.max_energy_range_threshold = 0;
80
domain.type = PACKAGE;
82
if (!strcmp(dir_entry->d_name, ".")
83
|| !strcmp(dir_entry->d_name, ".."))
85
thd_log_debug("RAPL domain dir %s\n", dir_entry->d_name);
86
path << dir_name << dir_entry->d_name << "/" << "name";
87
status = sys_fs.read(path.str(), buffer);
90
thd_log_debug("name %s\n", buffer.c_str());
91
if (fnmatch("package-*", buffer.c_str(), 0) == 0) {
92
domain.type = PACKAGE;
93
std::stringstream path;
94
path << dir_name << dir_entry->d_name << "/";
95
rapl_read_domains(path.str().c_str());
96
} else if (buffer == "core") {
98
} else if (buffer == "uncore") {
100
} else if (buffer == "dram") {
103
if (measure_mask & domain.type) {
104
domain.name = buffer;
105
domain.path = std::string(dir_name)
106
+ std::string(dir_entry->d_name);
107
domain_list.push_back(domain);
113
thd_log_debug("opendir failed %s :%s\n", strerror(errno),
114
rapl_sysfs.get_base_path());
118
thd_log_info("RAPL domain count %d\n", count);
121
void cthd_rapl_power_meter::rapl_enable_periodic_timer() {
122
pthread_attr_init(&thd_attr);
123
pthread_attr_setdetachstate(&thd_attr, PTHREAD_CREATE_DETACHED);
124
pthread_create(&poll_thread, &thd_attr, rapl_periodic_callback,
128
bool cthd_rapl_power_meter::rapl_energy_loop() {
131
unsigned long long counter;
132
unsigned long long diff;
135
if (!enable_measurement)
138
curr_time = time(NULL);
139
if ((curr_time - last_time) <= 0)
141
for (unsigned int i = 0; i < domain_list.size(); ++i) {
145
if (!domain_list[i].max_energy_range) {
148
_path = domain_list[i].path + "/" + "max_energy_range_uj";
149
status = sys_fs.read(_path, _buffer);
151
domain_list[i].max_energy_range = atoll(_buffer.c_str()) / 1000;
152
domain_list[i].max_energy_range_threshold =
153
domain_list[i].max_energy_range / 2;
156
path = domain_list[i].path + "/" + "energy_uj";
157
status = sys_fs.read(path, buffer);
159
counter = domain_list[i].energy_counter;
160
domain_list[i].energy_counter = atoll(buffer.c_str()) / 1000; // To milli Js
163
if (domain_list[i].half_way
164
&& domain_list[i].energy_counter
165
< domain_list[i].max_energy_range_threshold) {
167
domain_list[i].energy_cumulative_counter +=
168
domain_list[i].max_energy_range;
169
diff = domain_list[i].max_energy_range - counter;
171
domain_list[i].half_way = 0;
173
} else if (domain_list[i].energy_counter
174
> domain_list[i].max_energy_range_threshold)
175
domain_list[i].half_way = 1;
178
domain_list[i].power = (domain_list[i].energy_counter - counter
179
+ diff) / (curr_time - last_time);
180
thd_log_debug(" energy %d:%lld:%lld mj: %u mw \n",
182
domain_list[i].energy_cumulative_counter,
183
domain_list[i].energy_counter
184
+ domain_list[i].energy_cumulative_counter,
185
domain_list[i].power);
189
last_time = curr_time;
194
unsigned long long cthd_rapl_power_meter::rapl_action_get_energy(
196
unsigned long long value = 0;
198
for (unsigned int i = 0; i < domain_list.size(); ++i) {
199
if (type == domain_list[i].type) {
200
value = (domain_list[i].energy_counter
201
+ domain_list[i].energy_cumulative_counter) * 1000;
204
value = (domain_list[i].energy_counter
205
+ domain_list[i].energy_cumulative_counter) * 1000;
215
unsigned int cthd_rapl_power_meter::rapl_action_get_power(domain_type type) {
216
unsigned int value = 0;
221
for (unsigned int i = 0; i < domain_list.size(); ++i) {
222
if (type == domain_list[i].type) {
223
value = domain_list[i].power * 1000;
228
value = domain_list[i].power * 1000;
237
void cthd_rapl_power_meter::rapl_measure_power() {
238
if (rapl_present && enable_measurement)